x Java Java 8 JUnit JSON
  • XML
  • JDBC Spring Boot Microservices React Contact Us

    Mutation testing Java example

    While JUnit tests helps in validating business logic, Mutation testing further improves the quality of code by checking if tests cover all the scenarios by introducing mutants in the code. Although JUnit tests can be used to measure the code coverage, mutation testing goes one more level to validate logic by altering the code. For example if you are using '>' to compare numbers, mutation testing will introduce mutant in the code by changing '>' to '<' and then check if JUnit covers this condition.

    We can do mutation testing using PIT library which creates mutants at bytecode level without alterting the code. In this tutorial, we will show how to configure mutation testing using PIT and improve code coverage.

    Configuring and running mutation tests

    Step 1) Add maven dependencies

    To run and generate mutation test coverage report, add below dependencies & plugins. Notice that we can choose the Java package which will be target for mutation tests using <param><package name>.*</param>

    Maven dependencies

    <dependency>
        <groupId>org.pitest</groupId>
        <artifactId>pitest-parent</artifactId>
        <version>1.1.10</version>
        <type>pom</type>
    </dependency>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M1</version>
            </plugin>
            <plugin>
                <groupId>org.pitest</groupId>
                <artifactId>pitest-maven</artifactId>
                <version>1.4.3</version>
    
                <executions>
                    <execution>
                        <id>pit-report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>mutationCoverage</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.pitest</groupId>
                        <artifactId>pitest-junit5-plugin</artifactId>
                        <version>0.8</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <targetClasses>
                        <param>mutation.*</param>
                        </targetClasses>
                        <targetTests>
                            <param>mutation.*</param>
                    </targetTests>
                </configuration>
            </plugin>
        </plugins>
    </build>

    Gradle dependencies

    dependencies {
        classpath 'info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.4.6'
        pitest 'org.pitest:pitest-junit5-plugin:0.12'
    }
       
    apply plugin: 'info.solidsoft.pitest'
     
    pitest {
        testPlugin = 'junit5'
    }   

    Step 2) Write Numbers class which compares two numbers

    In the example below, we will first write a Numbers class which compares two numbers.

    package mutation;
    
    public int compare(Integer number1, Integer number2) {
            if (number1.intValue() > number2.intValue()) {
                return 1;
            }
            return -1;
    } 

    Step 3) Write NumbersTest class which tests compare() method of Numbers Class

    package mutation;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    import org.junit.jupiter.api.Test;
    
    public class NumbersTest {
    
        @Test
        public void testComapare() {
            Numbers numbers = new Numbers();
            assertEquals(false, numbers.compare(13, 12));
        }
    
    }    

    Step 4) Run mutation tests

    Run mutation tests using maven clean install command or manually using "mvn clean org.pitest:pitest-maven:mutationCoverage" command. Mutation test report will be generated under ".\target\pit-reports" directory

    You will see below report generated. Observer that even though line coverage is 75%, mutation coverage is only 50%. This is because mutation tests will also test the code ny changing "%gt;" to "%lt;" for which tests are missing.

    Mutation

    Mutation












    Mutation

    Mutation


















    Now we will add more junit tests to validate missed out scenarios and kill the mutants.

        @Test
        public void testComapare() {
            Numbers numbers = new Numbers();
            assertEquals(false, numbers.compare(13, 12));
            assertEquals(-1, numbers.compare(11, 12));
            assertEquals(-1, numbers.compare(11, 11));
        }    

    Now run mutation tests and observer report below. We have convered all the scenarios.

    Mutation

    Mutation












    Mutation

    Mutation


















    By default below mutators are configured but you can also configure the mutators

    • INCREMENTS_MUTATOR
    • VOID_METHOD_CALL_MUTATOR
    • RETURN_VALS_MUTATOR
    • MATH_MUTATOR
    • NEGATE_CONDITIONALS_MUTATOR
    • INVERT_NEGS_MUTATOR
    • CONDITIONALS_BOUNDARY_MUTATOR

    Custom mutation configuration

        <configuration>
            <mutators>
                <mutator>CONSTRUCTOR_CALLS</mutator>
                <mutator>NON_VOID_METHOD_CALLS</mutator>
            </mutators>
        </configuration>   

    References :

    PIT Mutation testing


    Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *











    Share This