Fuzzy Testing of Data/Model-centric applications
Many test cases for an application involve data defined by the data model. To achieve good test coverage it is customary to run the test cases for a variety of input data sets. This can be achieved by manually specifying input data. However, this is a complex task and it is easy to miss important input data and thereby miss bugs.
Fuzzy testing is about pseudo-randomly generated input data. A test case is written without specifying the exact input data, but rather with parameters driving the pseudo-random generation of input data for the test case. The test case can then be run a specified number of times with different seeds for the input data generation, thereby discovering bugs with input data you may not have selected manually.
This post shows a fuzzy testing framework for EMF models in action. It is based on JUnit 4 and existing tests can easily be migrated to run with it.
ModelMutator
First of all, this framework needs the ability to generate data based on a data model. We implemented a generator to create and mutate instances of EMF models in a deterministic way. The ModelMutator can generate instances of models based on a seed and different parameters. It can be used, for example, for performance tests with big models containing 1,000,000 objects:
ModelMutatorConfiguration config = new ModelMutatorConfiguration(ePackage, rootEObject, 1); config.setMinObjectsCount(1000000); ModelMutator.generateModel(config); |
The code fills the root EObject (root of the containment tree of the model instance) with 1,000,000 instances of EClasses declared in the given EPackage. It sets attribute values and cross-references based on the given seed to generate a well-connected graph with many different values.
Fuzzy Testing Framework
To use the fuzzy approach three ingredients are needed:
- A JUnit TestRunner to repeatedly run the same test with different data (seeds).
- A DataProvider to ‘inject’ different model instances into the test case.
- The ModelMutator to provide different model instances to the DataProvider.
The basic fuzzy JUnit runner executes a test repeatedly with different data. It is bound to a test case with the JUnit @RunWith annotation. The EMFDataProvider is driven by a set of annotations and injects data into a field annotated with @Data. The DataProvider itself is also registered with an annotation on the test case (@DataProvider annotation). The following snippet shows an example test using fuzzy testing:
@RunWith(FuzzyRunner.class) @DataProvider(EMFDataProvider.class) public class FuzzyTest { @Data private EObject root; @Test public void test(){ Assert.assertNotNull(root); } } |
Before the test() method is executed, the root object (@Data annotation) is already injected with generated data by the EMFDataProvider, so it will not be null. To configure parameters like the number of test runs there is a configuration for each test class which is stored in a file to ensure reproducibility:
<org.eclipse.emf.emfstore.fuzzy.emf.config:TestConfig seed="1" count="5000" testClass="org.eclipse.emf.emfstore.fuzzy.emf.test.FuzzyTest" id="_r78GhIvSEeGC3oFJZ-5HoM"> <mutatorConfig minObjectsCount="100"> <ePackage href="http://org/eclipse/example/bowling#/"/> </mutatorConfig> </org.eclipse.emf.emfstore.fuzzy.emf.config:TestConfig> |
This file can also be edited with a small EMF-based Editor (see screenshot).
After this quick configuration step, the test can be run with different pseudo-randomly generated data (see below).
As you can see, the test was executed 5,000 times in about 10 seconds.
The fuzzy runner can be executed with any implementation of the interface FuzzyDataProvider – like the EMFDataProvider – and therefore can also be used for any kind of test with data independent of EMF. It is already in active use to test the EMFStore model repository and helped us to find and fix quite a few bugs. To know how good your test-cases with the generated data really are, it is always a good idea to measure test coverage, e.g. with EclEmma.
Getting started
To get started, checkout the source code from our git repositories at eclipse.org, which you’ll find on the Getting involved page of EMFStore.
The plugins you need are available in the following two git repositories:
org.eclipse.emf.emfstore.core.git repository:
- org.eclipse.emf.emfstore.modelmutator
org.eclipse.emf.emfstore.other.git repository:
- org.eclipse.emf.emfstore.fuzzy
- org.eclipse.emf.emfstore.fuzzy.emf
- org.eclipse.emf.emfstore.fuzzy.emf.edit
- org.eclipse.emf.emfstore.fuzzy.emf.editor
- org.eclipse.emf.emfstore.fuzzy.emf.example: small example plugin configured to run with the example plugin, just run the FuzzyTest as JUnit Plug-in Test
- org.eclipse.emf.emfstore.fuzzy.emf.test: shows more advanced examples but also has a dependency to org.eclipse.emf.emfstore.client from the org.eclipse.emf.emfstore.core.git repository
Happy Testing!
Join me on Google+
Follow @EMFStore
Maximilian Koegel and Jonas Helming, EclipseSource Munich leads
Author: Maximilian Koegel



