rules_rust_mutants

Mutation testing for Rust crates built with rules_rust.

rust_mutation_test enumerates source-level mutations for a rust_library, compiles each mutant with the same rustc configuration as rust_test, and runs the crate's inline #[cfg(test)] tests against each mutant.

Rules

Setup

Bzlmod

Add the following to your MODULE.bazel file:

bazel_dep(name = "rules_rust_mutants", version = "{SEE_RELEASE_NOTES}")

WORKSPACE

If you're using WORKSPACE, load repositories with:

load("@rules_rust_mutants//:repositories.bzl", "rust_mutation_dependencies")

rust_mutation_dependencies()

Usage

load("@rules_rust_mutants//:defs.bzl", "rust_mutation_test")
load("@rules_rust//rust:defs.bzl", "rust_library")

rust_library(
    name = "my_lib",
    srcs = ["lib.rs"],
    edition = "2021",
)

rust_mutation_test(
    name = "my_lib_mutation_test",
    crate = ":my_lib",
)

Run with:

bazel test //:my_lib_mutation_test --test_output=all

Behavior Notes

  • Mutation generation uses cargo-mutants JSON output.
  • Mutation enumeration uses cargo mutants --list --json --diff --Zmutate-file ....
  • Rustc params are generated from rules_rust's canonical argument-construction pipeline (collect_inputs + construct_arguments).
  • mutants_config is forwarded as cargo mutants --config <path>.
  • By default, survived mutants fail the Bazel test target.
  • allow_survivors = True reports survivors without failing.
  • If mutation generation produces zero mutants, the Bazel target succeeds and prints No mutations generated..

Tooling

  • A hermetic cargo-mutants binary is built from source by this extension.
  • A Cargo binary from the active Rust toolchain is used for cargo-mutants internals.


Rules

rust_mutation_test

load("@rules_rust_mutants//:defs.bzl", "rust_mutation_test")

rust_mutation_test(name, allow_survivors, crate, exclude_re, mutants_config, rustc_flags)

Mutation testing for a Rust library crate.

rust_mutation_test:

  1. Enumerates source-level mutants with cargo-mutants.
  2. Builds rustc params from rules_rust's canonical argument construction pipeline (collect_inputs + construct_arguments).
  3. Runs baseline and per-mutant compile+test cycles against inline #[cfg(test)] tests from the crate.
  4. Fails if any mutant survives (unless allow_survivors = True).
  5. Succeeds and prints No mutations generated. when enumeration yields zero mutants.

Mutation enumeration mode:

  • Uses cargo mutants --list --json --diff --Zmutate-file ....

Example:

load("@rules_rust_mutants//:defs.bzl", "rust_mutation_test")

rust_library(
    name = "my_lib",
    srcs = ["lib.rs"],
)

rust_mutation_test(
    name = "my_lib_mutation_test",
    crate = ":my_lib",
)

Run with: bazel test //:my_lib_mutation_test --test_output=all

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
allow_survivorsIf True, survived mutants are reported but do not fail the test. Default is False (survivors fail).BooleanoptionalFalse
crateThe rust_library crate to mutation-test. The crate's inline #[cfg(test)] tests are compiled and run against each mutation.Labelrequired
exclude_reRegular expression patterns to exclude mutants. Each pattern is forwarded as cargo mutants --exclude-re <pattern>.List of stringsoptional[]
mutants_configOptional cargo-mutants configuration file. It is forwarded as cargo mutants --config <path>. If all mutants are filtered out, the target succeeds and reports no mutants.LabeloptionalNone
rustc_flagsAdditional flags passed through to rustc when compiling the baseline and mutant test binaries.List of stringsoptional[]