Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- New: `--cargo-test-arg` option to pass additional arguments to `cargo test`.

- New: `--sharding` option to control how mutants are distributed across multiple machines, with choices of `slice` or `round-robin`.

- Changed: The default sharding strategy is now `slice`; previously it was `round-robin`. Sliced sharding gives each worker better locality of reference due to testing changes to related packages, but may make the runtime more uneven between workers if some packages are slower to test than others.
Expand Down
14 changes: 14 additions & 0 deletions book/src/cargo-args.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,26 @@ excludes doctests. (If the doctests are numerous and slow, and not relied upon t
cargo mutants -- --all-targets
```

Alternatively, you can use the explicit `--cargo-test-arg` option, which can be repeated:

```shell
cargo mutants --cargo-test-arg=--all-targets --cargo-test-arg=--lib
```

Both formats can be used together if needed:

```shell
cargo mutants --cargo-test-arg=--lib -- --all-targets
```

These options can also be configured statically with the `additional_cargo_test_args` key in `.cargo/mutants.toml`:

```toml
additional_cargo_test_args = ["--jobs=1"]
```

When both command-line options and configuration are specified, arguments from `--cargo-test-arg`, then arguments after `--`, and finally configuration file arguments are all combined in that order.

## Arguments to test binaries

You can use a second double-dash to pass options through to the test targets:
Expand Down
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ pub struct Args {
)]
cargo_arg: Vec<String>,

/// Additional args for cargo test.
#[arg(long, allow_hyphen_values = true, help_heading = "Execution")]
cargo_test_arg: Vec<String>,

/// Pass remaining arguments to cargo test after all options and after `--`.
#[arg(last = true, help_heading = "Execution")]
cargo_test_args: Vec<String>,
Expand Down
84 changes: 80 additions & 4 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,13 @@ impl Options {

let options = Options {
additional_cargo_args: join_slices(&args.cargo_arg, &config.additional_cargo_args),
additional_cargo_test_args: join_slices(
&args.cargo_test_args,
&config.additional_cargo_test_args,
),
additional_cargo_test_args: args
.cargo_test_arg
.iter()
.chain(&args.cargo_test_args)
.chain(&config.additional_cargo_test_args)
.cloned()
.collect(),
all_features: args.all_features || config.all_features.unwrap_or(false),
annotations: args.annotations.resolve(),
baseline: args.baseline,
Expand Down Expand Up @@ -1146,6 +1149,79 @@ mod test {
assert!(!options.copy_vcs);
}

#[test]
fn cargo_test_arg_from_command_line() {
let args = Args::parse_from(["mutants", "--cargo-test-arg=--lib"]);
let config = Config::default();
let options = Options::new(&args, &config).unwrap();
assert_eq!(options.additional_cargo_test_args, vec!["--lib"]);
}

#[test]
fn cargo_test_arg_multiple_from_command_line() {
let args = Args::parse_from([
"mutants",
"--cargo-test-arg=--lib",
"--cargo-test-arg=--no-fail-fast",
]);
let config = Config::default();
let options = Options::new(&args, &config).unwrap();
assert_eq!(
options.additional_cargo_test_args,
vec!["--lib", "--no-fail-fast"]
);
}

#[test]
fn cargo_test_args_after_double_dash() {
let args = Args::parse_from(["mutants", "--", "--lib", "--no-fail-fast"]);
let config = Config::default();
let options = Options::new(&args, &config).unwrap();
assert_eq!(
options.additional_cargo_test_args,
vec!["--lib", "--no-fail-fast"]
);
}

#[test]
fn cargo_test_arg_and_cargo_test_args_combined() {
let args = Args::parse_from(["mutants", "--cargo-test-arg=--lib", "--", "--no-fail-fast"]);
let config = Config::default();
let options = Options::new(&args, &config).unwrap();
assert_eq!(
options.additional_cargo_test_args,
vec!["--lib", "--no-fail-fast"]
);
}

#[test]
fn cargo_test_arg_and_config_combined() {
let args = Args::parse_from(["mutants", "--cargo-test-arg=--lib"]);
let config = Config::from_str(indoc! { r#"
additional_cargo_test_args = ["--no-fail-fast"]
"#})
.unwrap();
let options = Options::new(&args, &config).unwrap();
assert_eq!(
options.additional_cargo_test_args,
vec!["--lib", "--no-fail-fast"]
);
}

#[test]
fn cargo_test_arg_cargo_test_args_and_config_combined() {
let args = Args::parse_from(["mutants", "--cargo-test-arg=--all-targets", "--", "--lib"]);
let config = Config::from_str(indoc! { r#"
additional_cargo_test_args = ["--no-fail-fast"]
"#})
.unwrap();
let options = Options::new(&args, &config).unwrap();
assert_eq!(
options.additional_cargo_test_args,
vec!["--all-targets", "--lib", "--no-fail-fast"]
);
}

#[test]
fn sharding() {
let args = Args::try_parse_from(["mutants", "--sharding=slice", "--shard=0/10"]).unwrap();
Expand Down
41 changes: 41 additions & 0 deletions tests/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,47 @@ fn additional_cargo_test_args() {
.success();
}

#[test]
fn cargo_test_arg_option() {
let testdata = copy_of_testdata("fails_without_feature");
run()
.args(["mutants", "--cargo-test-arg=--all-features", "-d"])
.arg(testdata.path())
.assert()
.success();
}

#[test]
fn cargo_test_arg_multiple_options() {
let testdata = copy_of_testdata("fails_without_feature");
run()
.args([
"mutants",
"--cargo-test-arg=--all-features",
"--cargo-test-arg=--no-fail-fast",
"-d",
])
.arg(testdata.path())
.assert()
.success();
}

#[test]
fn cargo_test_arg_and_additional_cargo_test_args_combined() {
let testdata = copy_of_testdata("fails_without_feature");
write_config_file(
&testdata,
r#"
additional_cargo_test_args = ["--no-fail-fast"]
"#,
);
run()
.args(["mutants", "--cargo-test-arg=--all-features", "-d"])
.arg(testdata.path())
.assert()
.success();
}

#[test]
fn features_config_option() {
let testdata = copy_of_testdata("fails_without_feature");
Expand Down
Loading