All Projects → llogiq → Mutagen

llogiq / Mutagen

Licence: other
Breaking your Rust code for fun and profit

Programming Languages

rust
11053 projects

Projects that are alternatives of or similar to Mutagen

Javascript Testing Best Practices
📗🌐 🚢 Comprehensive and exhaustive JavaScript & Node.js testing best practices (August 2021)
Stars: ✭ 13,976 (+3308.78%)
Mutual labels:  mutation-testing
dumbmutate
Simple mutation-testing
Stars: ✭ 32 (-92.2%)
Mutual labels:  mutation-testing
pitmp-maven-plugin
Maven plugin to handle multi module projects for PiTest
Stars: ✭ 36 (-91.22%)
Mutual labels:  mutation-testing
Gradle Pitest Plugin
Gradle plugin for PIT Mutation Testing
Stars: ✭ 144 (-64.88%)
Mutual labels:  mutation-testing
mutation-testing-elements
🗃 A schema for mutation testing results with the web components to visualise it 📊
Stars: ✭ 19 (-95.37%)
Mutual labels:  mutation-testing
dextool
Suite of C/C++ tooling built on LLVM/Clang
Stars: ✭ 81 (-80.24%)
Mutual labels:  mutation-testing
Stryker4s
Mutation testing for Scala. Work in progress...
Stars: ✭ 118 (-71.22%)
Mutual labels:  mutation-testing
mutant
mutation testing for R
Stars: ✭ 13 (-96.83%)
Mutual labels:  mutation-testing
Faultify
Byte Code Dotnet Mutation Utility
Stars: ✭ 16 (-96.1%)
Mutual labels:  mutation-testing
mutatest
Python mutation testing: test your tests! Safely run mutation trials without source code modifications and see what will get past your test suite.
Stars: ✭ 50 (-87.8%)
Mutual labels:  mutation-testing
Stryker Js
Mutation testing for JavaScript and friends
Stars: ✭ 2,043 (+398.29%)
Mutual labels:  mutation-testing
Mutpy
MutPy is a mutation testing tool for Python 3.x source code
Stars: ✭ 248 (-39.51%)
Mutual labels:  mutation-testing
mutode
Mutation testing for JavaScript and Node.js
Stars: ✭ 61 (-85.12%)
Mutual labels:  mutation-testing
Mutant
Automated code reviews via mutation testing - semantic code coverage.
Stars: ✭ 1,794 (+337.56%)
Mutual labels:  mutation-testing
vertigo
Mutation Testing for Ethereum Smart Contracts
Stars: ✭ 100 (-75.61%)
Mutual labels:  mutation-testing
Expect More
Curried Type Testing library, and Test Matchers for Jest
Stars: ✭ 124 (-69.76%)
Mutual labels:  mutation-testing
universalmutator
Regexp based tool for mutating generic source code across numerous languages
Stars: ✭ 105 (-74.39%)
Mutual labels:  mutation-testing
Muter
🔎 Automated mutation testing for Swift 🕳️
Stars: ✭ 293 (-28.54%)
Mutual labels:  mutation-testing
mutant-swarm
Mutation testing framework and code coverage for Hive SQL
Stars: ✭ 20 (-95.12%)
Mutual labels:  mutation-testing
pitest-descartes
Descartes supports developers to improve their test suites by reporting weak spots in covered code
Stars: ✭ 113 (-72.44%)
Mutual labels:  mutation-testing

Breaking your Rust code for fun & profit

this is an architecture-preview, not all components are there

This is a mutation testing framework for Rust code.

Mutation Testing

A change (mutation) in the program source code is most likely a bug of some kind. A good test suite can detect changes in the source code by failing ("killing" the mutant). If the test suite is green even if the program is mutated (the mutant survives), the tests fail to detect this bug.

Mutation testing is a way of evaluating the quality of a test suite, similar to code coverage. The difference to line or branch coverage is that those measure if the code under test was executed, but that says nothing about whether the tests would have caught any error.

How mutagen works

mutagen's core functionality is implemented via a procedural macro that transforms the source code. Known patterns of code are replaced by mutators with identical behavior unless activated. Activating a mutator at runtime alters its behavior - having the effect of a mutation.

The procedural macro has access to the bare AST. Information about inferred types, implemented traits, control flow, data flow or signatures of other functions are not available during the execution of procedural macros. Therefore, the mutations must be possible without additional type-information.

In order to be fast, it is necessary that the compilation of the test suite is performed only once. To achieve this, all mutations are baked into the code once and are selected at runtime via an environment variable. This means the mutations are not allowed to produce code that fails to compile.

This project is basically an experiment to see what mutations we can still apply under those constraints.

Using mutagen

Note: The version of mutagen (0.2.0) referenced in this README is not yet released on crates.io. To install and use an earlier, released version, you can follow the instructions on crates.io mutagen crate.

You need Rust nightly to compile the procedural macro.

Add the library mutagen as a dev-dependency to your Cargo.toml referencing this git repository:

[dev-dependencies]
mutagen = {git = "https://github.com/llogiq/mutagen"}

To use the attribute #[mutate], you need to import it.

#[cfg(test)]
use mutagen::mutate;

Now you can advise mutagen to mutate any function or method by prepending #[cfg_attr(test, mutate)]. The use of cfg_attr ensures the #[mutate] attribute will only be active in test mode. The repository contains an example that shows how mutagen could be used.

Running mutagen

Install cargo-mutagen, which can be done by running cargo install cargo-mutagen. Run cargo mutagen on the project under test for a complete mutation test evaluation.

The mutants can also be run manually: cargo test will compile code and write the performed mutations to target/mutagen/mutations. This file contains ids and descriptions of possible mutations. Then, the environment variable MUTATION_ID can be used to activate a single mutation as defined by the mutations file. The environment variable can be set before calling the test suite, i.e. MUTATION_ID=1 cargo test, MUTATION_ID=2 .., etc. For every mutation count at of least one, the test suite should fail

You can run cargo mutagen -- --coverage in order to reduce the time it takes to run the mutated code. When running in this mode, it runs the test suite at the beginning of the process and checks which tests are hitting mutated code. Then, for each mutation, instead of running the whole test suite again, it executes only the tests that are affected by the current mutation. This mode is especially useful when the test suite is slow or when the mutated code affects a little part of it.

If you referenced mutagen in your cargo.toml via the git repository as noted in the Using Mutagen section, you will probably want to install the development version of cargo-mutagen. To install the development version, run cargo install in the mutagen-runner dir of this repository. Running cargo install --force might be necessary to overwrite any existing cargo-mutagen binary.

A Word of Warning

mutagen will change the code you annotate with the #[mutate] attribute. This can have dire consequences in some cases. However, functions not annotated with #[mutate] will not be altered.

Do not use #[mutate] for code that can cause damage if buggy. By corrupting the behavior or sanity checks of some parts of the program, dangerous accidents can happen. For example by overwriting the wrong file or sending credentials to the wrong server.

Use #[mutate] for tests only. This is done by always annotating functions or modules with #[cfg_attr(test, mutate)] instead, which applies the #[mutate] annotation only in test mode. If a function is annotated with plain #[mutate] in every mode, the mutation-code is baked into the code even when compiled for release versions. However, when using mutagen as dev-dependency, adding a plain #[mutate] attribute will result in compilation errors in non-test mode since the compiler does not find the annotation.

Use mutagen as dev-dependency, unless otherwise necessary. This ensures that no code from mutagen is part of your released library or application.

Limitations of Mutations

No mutations will be introduced in unsafe-blocks and unsafe functions. Such mutations would probably break some invariants. Moreover, mutations in unsafe code could lead to undefined behavior that cannot be observed by any testcase.

const and static expressions cannot be mutated. They are evaluated at compile-time and mutagen can only affect code that can alter its behavior at run-time. Array lengths and global constants are examples of const expressions.

Patterns cannot be mutated. Mutations are introduced by injecting calls to mutagen-internal functions, which cannot be placed inside patterns.

Contributing

Issues and PRs welcome! See CONTRIBUTING.md on how to help.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].