diff --git a/README.md b/README.md index cbef997a..ed5d198c 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,11 @@ OPTIONS: --no-fail-fast Run all tests regardless of failure + --ignore-run-fail + Run all tests regardless of failure and generate report + + If tests failed but report generation succeeded, exit with a status of 0. + -q, --quiet Display one character per test instead of one line diff --git a/src/cli.rs b/src/cli.rs index e5498eb3..150fdd01 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -56,6 +56,17 @@ pub(crate) struct Args { /// Run all tests regardless of failure #[clap(long)] pub(crate) no_fail_fast: bool, + /// Run all tests regardless of failure and generate report + /// + /// If tests failed but report generation succeeded, exit with a status of 0. + #[clap( + long, + // --ignore-run-fail implicitly enable --no-fail-fast. + conflicts_with = "no-fail-fast", + // --ignore-run-fail without run is no-op. + conflicts_with = "no-run", + )] + pub(crate) ignore_run_fail: bool, /// Display one character per test instead of one line #[clap(short, long, conflicts_with = "verbose")] pub(crate) quiet: bool, diff --git a/src/main.rs b/src/main.rs index 136735b4..49c0017b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -311,12 +311,36 @@ fn run_test(cx: &Context, args: &Args) -> Result<()> { cargo.arg("-Z"); cargo.arg("doctest-in-workspace"); } - cargo::test_args(cx, args, &mut cargo); - if term::verbose() { - status!("Running", "{}", cargo); + if args.ignore_run_fail { + let mut cargo_no_run = cargo.clone(); + cargo_no_run.arg("--no-run"); + cargo::test_args(cx, args, &mut cargo_no_run); + if term::verbose() { + status!("Running", "{}", cargo_no_run); + cargo_no_run.stdout_to_stderr().run()?; + } else { + // Capture output to prevent duplicate warnings from appearing in two runs. + cargo_no_run.run_with_output()?; + } + drop(cargo_no_run); + + cargo.arg("--no-fail-fast"); + cargo::test_args(cx, args, &mut cargo); + if term::verbose() { + status!("Running", "{}", cargo); + } + if let Err(e) = cargo.stdout_to_stderr().run() { + warn!("{}", e); + } + } else { + cargo::test_args(cx, args, &mut cargo); + if term::verbose() { + status!("Running", "{}", cargo); + } + cargo.stdout_to_stderr().run()?; } - cargo.stdout_to_stderr().run()?; + Ok(()) } diff --git a/src/process.rs b/src/process.rs index c07fbd1f..cccf613c 100644 --- a/src/process.rs +++ b/src/process.rs @@ -23,6 +23,7 @@ macro_rules! cmd { // A builder for an external process, inspired by https://github.com/rust-lang/cargo/blob/0.47.0/src/cargo/util/process_builder.rs #[must_use] +#[derive(Clone)] pub(crate) struct ProcessBuilder { /// The program to execute. program: OsString, diff --git a/tests/long-help.txt b/tests/long-help.txt index 19d1e9e5..9c678abc 100644 --- a/tests/long-help.txt +++ b/tests/long-help.txt @@ -107,6 +107,11 @@ OPTIONS: --no-fail-fast Run all tests regardless of failure + --ignore-run-fail + Run all tests regardless of failure and generate report + + If tests failed but report generation succeeded, exit with a status of 0. + -q, --quiet Display one character per test instead of one line diff --git a/tests/short-help.txt b/tests/short-help.txt index 91f94606..9928f4d1 100644 --- a/tests/short-help.txt +++ b/tests/short-help.txt @@ -72,6 +72,9 @@ OPTIONS: --no-fail-fast Run all tests regardless of failure + --ignore-run-fail + Run all tests regardless of failure and generate report + -q, --quiet Display one character per test instead of one line