Fork me on GitHub

Running Descartes on your project

Stable releases of Descartes are available from Maven Central. Descartes is a plugin for PIT, so they have to be used together. PIT integrates with majors test and build tools such as Maven, Ant and Gradle.

Using Maven

The minimum configuration to use Descartes in a Maven project is the following:

<plugin>
  <groupId>org.pitest</groupId>
  <artifactId>pitest-maven</artifactId>
  <version>1.20.2</version>
  <configuration>
    <mutationEngine>descartes</mutationEngine>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>eu.stamp-project</groupId>
      <artifactId>descartes</artifactId>
      <version>1.3.4</version>
    </dependency>
  </dependencies>
</plugin>

This configures PIT for the project, adds Descartes as a dependency of PIT and sets Descartes as the mutation engine to use. Later, one needs to run the mutation coverage goal provided by the PIT Maven plugin as follows:

cd my-project-under-test
mvn clean package # ensures clean state
mvn org.pitest:pitest-maven:mutationCoverage

Specifying mutation operators

The mutation operators must be specified in the pom.xml file. Each operator identifier should be added to the mutators element inside the configuration element. void and null operators are identified by void and null respectively. The values for the constant mutation operator can be specified using the regular literal notation used in a Java program. For example true, 1, 2L, 3.0f, 4.0, 'a', "literal", represent boolean, int, long, float, double, char, string constants. Negative values and binary, octal and hexadecimal bases for integer constants are supported as stated by the language specification. In order to specify a byte or short value, a cast-like notation can be used: (short) -1, (byte)0x1A.

The following configuration:

<mutators>
    <mutator>void</mutator>
    <mutator>4</mutator>
    <mutator>"some string"</mutator>
    <mutator>false</mutator>
</mutators>

will instruct the tool to use the void operator. The constant operator will replace the body of every method returning int with return 4; and will use "some string" and false for every string and boolean method.

By default, Descartes uses the following operators:

<mutators>
  <mutator>void</mutator>
  <mutator>null</mutator>
  <mutator>true</mutator>
  <mutator>false</mutator>
  <mutator>empty</mutator>
  <mutator>0</mutator>
  <mutator>1</mutator>
  <mutator>(byte)0</mutator>
  <mutator>(byte)1</mutator>
  <mutator>(short)0</mutator>
  <mutator>(short)1</mutator>
  <mutator>0L</mutator>
  <mutator>1L</mutator>
  <mutator>0.0</mutator>
  <mutator>1.0</mutator>
  <mutator>0.0f</mutator>
  <mutator>1.0f</mutator>
  <mutator>'\40'</mutator>
  <mutator>'A'</mutator>
  <mutator>""</mutator>
  <mutator>"A"</mutator>
</mutators>

All the goals defined by the pitest-maven plugin work with Descartes. For more information check the Maven plugin's web page.

Configuring stop methods

To configure the stop methods under consideration Descartes provides a STOP_METHODS feature. This feature is enabled by default. The parameter exclude can be used to prevent certain methods to be treated as stop methods and bring them back to the analysis. This parameter can take any of the following values:

exclude Method description Example
empty void methods with no instruction. public void m() {}
enum Methods generated by the compiler to support enum types (values and valueOf).
to_string toString methods.
hash_code hashCode methods.
deprecated Methods annotated with @Deprecated or belonging to a class with the same annotation. @Deprecated public void m() {...}
synthetic Methods generated by the compiler.
getter Simple getters. public int getAge() { return this.age; }
setter Simple setters. Includes also fluent simple setters. public void setX(int x) { this.x = x; } and public A setX(int x){ this.x = x; return this; }
constant Methods returning a literal constant. public double getPI() { return 3.14; }
delegate Methods implementing simple delegation. public int sum(int[] a, int i, int j) {return this.adder(a, i, j); }
clinit Static class initializers.
return_this Methods that only return this. public A m() { return this; }
return_param Methods that only return the value of a real parameter public int m(int x, int y) { return y; }
kotlin_setter Setters generated for data classes in Kotlin (New in version 2.1.6)

So, for example, if we don't want to exclude deprecated methods and mutate them, the following snippet should be added under the configuration element:

<features>
  <feature>
  <!-- This will allow descartes to mutate deprecated methods -->
    +STOP_METHODS(except[deprecated])
  </feature>
</features>

More than one group can be excluded at the same time:

<features>
  <feature>
  <!-- This will allow descartes to mutate toString and enum generated methods -->
    +STOP_METHODS(except[to_string] except[enum])
  </feature>
</features>

The feature can be completely disabled:

<features>
  <feature>
  <!--No method is considered as a stop method and therefore all of them will be mutated -->
    -STOP_METHODS()
  </feature>
</features>

Configuring reports

Descartes include several reporting formats:

  • JSON: for a general mutation testing report using the JSON file format. It can be used with Gregor.
  • METHODS: that produces a methods.json file with the list of all methods analyzed and categorized according to the mutation testing result.
  • ISSUES: a human-readable report containing only the methods with testing issues.

They can be configured and combined as regular PIT report formats:

<plugin>
  <groupId>org.pitest</groupId>
  <artifactId>pitest-maven</artifactId>
  <version>1.20.2</version>
  <configuration>
    <outputFormats>
      <value>JSON</value>
      <value>METHODS</value>
      <value>ISSUES</value>
    </outputFormats>
    <mutationEngine>descartes</mutationEngine>
  </configuration>
    <dependencies>
    <dependency>
      <groupId>eu.stamp-project</groupId>
      <artifactId>descartes</artifactId>
      <version>1.3.4</version>
    </dependency>
  </dependencies>
</plugin>

Other filters

From version 1.2.6 Descartes includes AVOID_NULL as a feature preventing the null operator to mutate a method marked with @NotNull. The feature is active by default.

It can be removed by adding the following configuration:

<features>
  <feature>
    -AVOID_NULL()
  </feature>
</features>

From version 1.3 Descartes includes DO_NOT_MUTATE as a feature preventing the mutation of method and classes annotated with @DoNotMutate. The feature is active by default.

It can be removed by adding the following configuration:

<features>
  <feature>
    -DO_NOT_MUTATE()
  </feature>
</features>

From version 1.3 Descartes includes SKIP_SHORT as a feature to skip methods shorter than a given number of lines. The feature is not active by default. To activate add the following configuration:

<features>
  <feature>
    +SKIP_SHORT()
  </feature>
</features>

The number of lines can be configured as follows:

+SKIP_SHORT(lines[3])

The line threshold is equal to 5 by default.

Using Gradle

Follow the instructions to set up PIT for a project that uses Gradle. Add Descartes as a dependency of the pitest task

pitest 'eu.stamp-project:descartes:1.3.4'

then specify descartes in the mutationEngine option inside the plugin configuration.

An example of the final configuration could be:

plugins {
    id 'java'
    id 'info.solidsoft.pitest' version '1.5.1'
}

// Other configurations

repositories {
    mavenCentral()
    mavenLocal()
}

dependencies {
    testImplementation group: 'junit', name: 'junit', version: '4.13.1'
    pitest 'eu.stamp-project:descartes:1.3.4'
}

pitest {
  mutationEngine = "descartes"
  pitestVersion = "1.20.2"
}

The pitestVersion property has to be specified to avoid version issues with the default version shipped with the Gradle plugin. At last, run the pitest task for the project under test:

gradle pitest

Specifying operators

To specify a custom selection of mutation operators, use the operators property in the pitest block as follows:

mutators = [ '1.2', 'true', 'optional', '"a"' ]

This mutates methods returning double values with 1.2, boolean methods with true, methods returning Optional and methods returning String.

See the Maven section for more details on the operator identifiers.

Configuring stop methods

As explained in the Maven section, Descartes skips some methods that are usually of no interest like simple getters and setters. However, these methods can be reincorporated to the analysis using the STOP_METHODS feature. The following removes all stop methods but allows mutating simple setters:

features = ['+STOP_METHODS(except[setter])']

To allow all stop methods do:

features = ['-STOP_METHODS()']

Descartes custom output formats can be configured as follows:

outputFormats = ['ISSUES', 'METHODS', 'JSON']

Other features

Descartes includes AVOID_NULL and DO_NOT_MUTATE features as explained previously. These are active by default. To disable this features it is enough to add the following configuration to the pitest block:

features = ['-AVOID_NULL()']
features = ['-DO_NOT_MUTATE()']

Running from the command line

Descartes can be used when invoking PIT from the command line. To do this, follow the instructions to run PIT, include Descartes in the classpath specification and add --mutationEngine=descartes.

Installing and building from source

In a terminal, clone the repository:

git clone https://github.com/STAMP-project/pitest-descartes.git

switch to the cloned folder:

cd  pitest-descartes

install Descartes using the regular Apache Maven commands:

mvn install

After installing the package, PIT should be able to find the Descartes mutation engine.