Sonar Pitest Plugin
PIT is a mutation testing tool for java. You can check out the official pitest web site for more details on mutation testing and PIT.
Long story short, mutation testing is a very smart way to check the relevance of unit tests. The main idea is to alter the tested code and check that at least one unit test fails. An alteration of the code is called a "mutant". A mutant has "survived" the tests if there is no test failure.
The goal of this plugin is to bring PIT results to sonar. Right now the integration of these result is quite simple, "survived mutants" on code covered by tests are seen as sonar violations.
Usage & Installation
Limitations of mutation testing
This section is not specific to PIT but since mutation testing is not yet a mainstream method... Here are a couple of general advises and warnings:
- Mutation testing is very CPU time expensive. It is really important to control the scope of mutation testing in order to keep acceptable sonar analysis times. See below for tips on analysis time.
- Mutation testing works on true unit tests. Do not try to use it on integration tests, you might mess up your database, file system, whatever external system used by your integration tests.
Sonar server installation
On the sonar side, just copy the sonar-pitest-plugin jar to the extensions/plugins directory just like any regular sonar plugin.
Since mutation testing is not (yet) officially supported by sonar, this plugin acts as a "single rule" rule engine... This rule, named "Survived mutant", is disabled by default and hence needs to be activated when pitest is used.
Project build setup
You have two options in order to produce PIT reports for sonar. You can either let the sonar plugin run PIT or you can run PIT prior to the sonar analysis.
PIT launched by Sonar
This is the recommended way to go if your build is based on maven 2. Most mandatory PIT configuration entries will be set using information provided by the pom.xml file of your project. You just need to activate PIT execution and specify which classes to mutate and tests to execute. Below an example:
Note: you will find at the bottom of this page an exhaustive description of all the configuration parameters.
The example above tells PIT to mutate classes from packages starting with "com.acme.tools.commons". It also specifies that test classes are located in packages starting with "com.acme.tools.commons".
PIT launched before Sonar
You can launch PIT using the PIT maven plugin or the command line runner. PIT execution must be done before sonar analysis. You also need to specify the "reuseReport" mode of the PIT sonar plugin.
Pit needs to be configured in order to generate XML reports. Be aware that PIT default behavior is to generate HTML reports. Below a simple configuration example for maven :
inScopeClasses and targetClasses parameters indicated the classes of the system under test where mutations can be performed. In the example above, all the classes from the com.acme.tools.commons package and sub packages may be altered.
Once configured in the maven pom file, you need to run PITusing the following command "mvn org.pitest:pitest-maven:mutationCoverage".
Note : Of course, all the configuration options are clearly explained in the official pitest documentation.
Last but not least, you need to run a sonar analysis with the PIT plugin activated in "reuseReport" mode. The following command would do the job :
"mvn sonar:sonar -Dsonar.pitest.mode=reuseReport"
By default sonar will search the latest PIT report in "target/pit-reports". You can specify another location using property "sonar.pitest.reportsDirectory".
You will find below the list of all the available configuration parameters.
Basic configuration properties
Below the exhaustive list of configuration properties of the sonar pitest plugin.
Pitest activation mode
Possible values : 'skip', 'active' (not supported yet) and 'reuseReport'
Path to the pitest reports
Path used when mode "reuseReport" is activate to locate pitest xml reports.
|Classes to include in mutation tests||sonar.pit.target.classes||groupId*||The classes to be mutated. This is expressed as a comma seperated list of globs. For example com.mycompany.* or com.mycompany.package.*, com.mycompany.packageB.Foo, com.partner.*. When maven is used, the default value is 'groupId*'|
|Tests to run||sonar.pit.target.tests||sonar.pit.target.classes||A comma seperated list of globs can be supplied to this parameter to limit the tests available to be run. If not specified, the value of "sonar.pit.target.classes" is used (not recommended)|
Advanced configuration properties
|TestNG Groups to include||sonar.pit.included.testng.groups||List of TestNG groups to include in mutation analysis.|
|TestNG Groups to exclude||sonar.pit.excluded.testng.groups||List of TestNG groups to exclude from mutation analysis.|
|Throw error if no mutations found||sonar.pit.fail.when.no.mutations||true|
Whether to throw error when no mutations found.
|Arguments to pass to child processes||sonar.pit.jvm.args||List of arguments to use when PIT launches child processes. This is most commonly used to increase the amount of memory available to the process, but may be used to pass any valid JVM argument.|
|Maximum number of mutations to allow per class||sonar.pit.max.mutations.per.class||-1 (no limit)||The maximum number of mutations to create per class. Use 0 or -ve number to set no limit.|
|Constant amount of additional time to allow for timeouts||sonar.pit.timeout.constant||3000||Constant amount of additional time to allow a test to run for (after the application of the timeoutFactor) before considering it to be stuck in an infinite loop.|
|Weighting to allow for timeouts||sonar.pit.timeout.factor||1.25||A factor to apply to the normal runtime of a test when considering if it is stuck in an infinite loop.|
|Mutation operators to apply||sonar.pit.mutators||INVERT_NEGS, RETURN_VALS, MATH, VOID_METHOD_CALLS, NEGATE_CONDITIONALS, CONDITIONALS_BOUNDARY, INCREMENTS||See official PIT documentation for the list of available mutators:|
|Mutate static initializers||sonar.pit.mutate.static.initializers||false||Whether or not to create mutations in static initializers. Defaults to false.|
|Threads||sonar.pit.threads||1||Number of threads to use|
|Maximum dependency distance||sonar.pit.max.dependency.distance||-1 (no limit)|
Maximum distance to look from test to class. Relevant when mutating static initializers
Calls excluded from mutations
major logging framework APIs
List of packages and classes which are to be considered outside the scope of mutation
Classes not to mutate or run tests from
List of globs to match against class names. Matching classes will be excluded from mutation. Matching test classes will not be run (note if a suite includes an excluded class, then it will “leak” back in).
|Methods not to mutate||sonar.pit.excluded.methods||List of globs to match against method names. Methods matching the globs will be exluded from mutation.|
Not useful when maven is used.
You can check out the quickstart section of the official pitest web site for detailed instructions.