Mutation testing

Mutants generation

The class ConfiguredMutagen allows to easilly generate mutants using a configuration file specifying the mutation operators configuration:

import static be.unamur.transitionsystem.dsl.TransitionSystemXmlLoaders.*;
import static be.unamur.transitionsystem.dsl.test.mutation.ConfiguredMutagen.*;

public Main{
    public static void main(String[] args){
        LabelledTransitionSystem lts = new MyLTS().getTransitionSystem();
        // Loads the mutation operators configuration

        // E.g., ennumerative mutants generation
        configure("operatorsConfig.xml")
            .outputDir("mutants/") // Generates mutants in the given folder
            .mutate(lts);

        // E.g., FMM generation
        configure("operatorsConfig.xml")
            .ftsMutant("fmm.fts") // Generates FMM's FTS with given name
            .tvlMutant("fmm.tvl") // Generates FMM's FD in TVL format
            .mutate(lts);

        // E.g., ennumerative and FMM generation (will generate the same mutants)
        configure("operatorsConfig.xml")
            .outputDir("mutants/") // Generates mutants in the given folder
            .ftsMutant("fmm.fts") // Generates FMM's FTS with given name
            .tvlMutant("fmm.tvl") // Generates FMM's FD in TVL format
            .mutate(lts);   
    }
}

Here is a exemple of configuration file (in XML):

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <mutantsSize>200</mutantsSize> <!-- Default mutant size (may be redefined) -->
    <!-- Default selection strategies for each operator (may be redefined) -->
    <actionSelection>be.unamur.transitionsystem.test.mutation.RandomSelectionStrategy</actionSelection>
    <stateSelection>be.unamur.transitionsystem.test.mutation.RandomSelectionStrategy</stateSelection>
    <transitionSelection>be.unamur.transitionsystem.test.mutation.RandomSelectionStrategy</transitionSelection>
    <unique>true</unique> <!-- Default uniqueness of each mutant (may be redefined) -->
    <!-- Operators -->
    <operators>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.ActionExchange</class>
        </operator>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.ActionMissing</class>
        </operator>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.StateMissing</class>
        </operator>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.TransitionAdd</class>
        </operator>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.TransitionDestinationExchange</class>
        </operator>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.TransitionMissing</class>
        </operator>
        <operator>
            <class>be.unamur.transitionsystem.test.mutation.WrongInitialState</class>
            <mutantsSize>100</mutantsSize>
            <actionSelection>be.unamur.transitionsystem.test.mutation.RandomSelectionStrategy</actionSelection>
            <stateSelection>be.unamur.transitionsystem.test.mutation.RandomSelectionStrategy</stateSelection>
            <transitionSelection>be.unamur.transitionsystem.test.mutation.RandomSelectionStrategy</transitionSelection>
            <unique>false</unique>
        </operator>
    </operators>
</config>

It is also possible to configure a particular mutation operator for a given transition system using the Mutagen class:

import static be.unamur.transitionsystem.dsl.TransitionSystemXmlLoaders.*;
import static be.unamur.transitionsystem.dsl.test.mutation.Mutagen.*;
import be.unamur.transitionsystem.test.mutation.*;

public Main{
    public static void main(String[] args){
        LabelledTransitionSystem lts = new MyLTS().getTransitionSystem();
        FeaturedTransitionSystem fts = new FeaturedTransitionSystem(lts);
        // Initialise the operator for the given transition system
        MutationOperator op = transitionMissing(lts)
            .transitionSelectionStrategy(new RandomSelectionStrategy())
            .done();

        // Apply the operator 
        op.apply();
        // Get the mutant transition system (enumerative version)
        LabelledTransitionSystem mutant = (LabelledTransitionSystem) op.result();
        // Enrich the FMM's FTS with the new mutant
        op.transpose(fts);
        // Get the feature ID used in the FMM's FTS (should be added to the used feature diagram)
        String mutantFeatureId = op.getFeatureId();
    }
}

Featured Mutants Model

The FeaturedMutantsModel class in the be.unamur.transitionsystem.test.mutation package allows to compactly represent a set of mutants using a FMM. It may be build using mutation operators or using a mutation configuration.

import be.unamur.transitionsystem.test.mutation.FeaturedMutantsModel;
import be.unamur.transitionsystem.test.mutation.MutationConfiguration;
import be.unamur.fts.fexpression.configuration.Configuration;

public static void main(String[] args){
        LabelledTransitionSystem lts = new MyLTS().getTransitionSystem();
        // Initialise the FMM
        FeaturedMutantsModel fmm = new FeaturedMutantsModel(lts);
        // Initialise the operatro for the given transition system
        MutationOperator op = transitionMissing(lts)
            .transitionSelectionStrategy(new RandomSelectionStrategy())
            .done();
        // Apply the operator 
        fmm.mutate(op);
        // Apply mutations from a configuration file
        fmm.mutate(new MutationConfiguration("mutations.xml"));
        // Iterate over 2nd order mutants 
        Iterator<Configuration> it = fmm.getMutantsConfigs(2);
        while(it.hasNext()){
            LabelledTransitionSystem mutant = fmm.getMutant(it.next());
            // ...
        }
    }
}

Mutants execution

To execute a test case on a FMM, one may use one of the several static methods defined in FeaturedMutantsModels in package be.unamur.transitionsystem.dsl.test.mutation.

import be.unamur.transitionsystem.test.mutation.FeaturedMutantsModel;
import be.unamur.transitionsystem.test.mutation.MutationConfiguration;
import static be.unamur.transitionsystem.dsl.test.mutation.FeaturedMutantsModels.*;
import static be.unamur.transitionsystem.dsl.test.TestCaseXmlLoader.*;

public static void main(String[] args){
        LabelledTransitionSystem lts = new MyLTS().getTransitionSystem();
        // Initialise the FMM
        FeaturedMutantsModel fmm = new FeaturedMutantsModel(system);
        fmm.mutate(new MutationConfiguration("mutations.xml"));
        // Load set of test cases 
        Iterator<TestCase> it = loadLtsTestCases("mytests.xml");
        while(it.hasNext(){
            // Get the alive mutants
            FExpression alive = getAliveMutants(it.next(), fmm);
        }
    }
}