The tool is used to test the quality of the test suite and the source code.
The program logic is quite simple, the tool works using the following principles:
- Runs tests on the original source code to ensure the original tests are valid.
- Internally runs the Move Mutator tool to generate mutants.
- Runs the tests for all mutants to check if the mutants are killed by the original test suite.
If the mutants are not killed, it might indicate the quality of the test suite could be improved, or in some rare cases, it might indicate an error in the original source code.
Move Mutation Tester tool can be used on Move packages (projects) which can compile successfully and have valid tests that are passing. Using filters, it is possible to run the tool only on certain mutants filtered by:
- Module name (
--mutate-modules
argument) - Function name (
--mutate-functions
argument)
The tool cannot be used with single Move files since, to run tests, the whole Move project structure with the manifest file is required.
The tool generates a report in a JSON format. The report contains information about the number of mutants tested and killed and also the differences between the original and modified code.
Build the whole repository first:
cargo build --release
Check if the tool is working properly by running its tests via the nextest
tool:
# Using the release build for tests due to test duration
cargo nextest run -r -p move-mutation-test
To start the mutation test, run the following command from the repo directory:
./target/release/move-mutation-test run --package-dir move-mutator/tests/move-assets/simple -o report.txt
The above command will store the report in a file report.txt
.
A shortened sample output for the above command will look as follows:
Total mutants tested: 229
Total mutants killed: 203
╭────────────────────────────────────────────────┬────────────────┬────────────────┬────────────╮
│ Module │ Mutants tested │ Mutants killed │ Percentage │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/Operators.move::Operators::and │ 2 │ 2 │ 100.00% │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/Operators.move::Operators::div │ 5 │ 5 │ 100.00% │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/Operators.move::Operators::eq │ 5 │ 5 │ 100.00% │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/Operators.move::Operators::gt │ 6 │ 6 │ 100.00% │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/StillSimple.move::StillSimple::sample1 │ 24 │ 16 │ 66.67% │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/StillSimple.move::StillSimple::sample2 │ 11 │ 10 │ 90.91% │
├────────────────────────────────────────────────┼────────────────┼────────────────┼────────────┤
│ sources/Sum.move::Sum::sum │ 4 │ 4 │ 100.00% │
╰────────────────────────────────────────────────┴────────────────┴────────────────┴────────────╯
The sample report.txt
generated for the above command contains useful info that can be paired with the display-report
option:
$ move-mutation-test display-report coverage -p report.txt --modules Sum
The legend is shown below in the table format
===================================┬==================================
mutants killed / mutants in total │ Source code file path
===================================┼==================================
<examples below> │ <Line>
│
│ Line without any mutants
6/8 │ Some mutants killed on this line
│ Another line without any mutants
10/10 │ All mutants killed on this line
0/4 │ No mutants killed on this line
│ One final line without mutants
=====┬=======================================
│ sources/Sum.move
=====┼=======================================
│ module TestAccount::Sum {
│ fun sum(x: u128, y: u128): u128 {
4/4 │ let sum_r = x * y;
│ spec {
│ assert sum_r == x+y;
│ };
│
│ sum_r
│ }
│
│ #[test]
│ fun sum_test() {
│ assert!(sum(2, 2) == 4, 0);
│ assert!(sum(0, 5) == 5, 0);
│ assert!(sum(100, 0) == 100, 0);
│ assert!(sum(0, 0) == 0, 0);
│ }
│ }
You should see different results for different modules as it depends on the
quality of the source code and the test suites. Some modules, like Sum
, have good
tests and all mutants are killed, while some others, like Operators
may not and some mutants remain alive.
It's recommended to generate a report in a JSON format and analyze it to see which mutants are not killed, and what the differences are between the original and modified code. This can help improve the test suite, or it may indicate an error in the original source code.
The tool respects RUST_LOG
variable, and it will print out as much information as the variable allows.
There is possibility to enable logging only for the specific modules.
Please refer to the env_logger documentation for more details.
You can try to run the tool using other examples from the move-mutator
tests like:
./target/release/move-mutation-test run --package-dir move-mutator/tests/move-assets/breakcontinue
To check possible options, use the --help
option with any command/subcommand.
In below examples, the RUST_LOG
flag is used to provide a more informative output.
To use the tool on only the Operators
module for the project simple
, run:
RUST_LOG=info ./target/release/move-mutation-test run --package-dir move-mutator/tests/move-assets/simple -o report.txt --move-2 --mutate-modules Operators
./target/release/move-mutation-test display-report coverage -p report.txt --modules Operators
To use the tool only on functions called sum
for the project simple
, run:
RUST_LOG=info ./target/release/move-mutation-test run --package-dir move-mutator/tests/move-assets/simple -o report.txt --move-2 --mutate-functions sum
./target/release/move-mutation-test display-report coverage -p report.txt --modules Operators,Sum
In the output for the above command, the tool will mutate both the Operators::sum
and Sum::sum
functions.
If the user wants to mutate only the sum
function in the Sum
module, the user can use this command:
RUST_LOG=info ./target/release/move-mutation-test run --package-dir move-mutator/tests/move-assets/simple -o report.txt --move-2 --mutate-functions sum --mutate-modules Sum
./target/release/move-mutation-test display-report coverage -p report.txt --modules Sum