DEV Community

Cover image for [Rust Guide] 11.6. Controlling Test Execution - Parallel and Sequential Tests
SomeB1oody
SomeB1oody

Posted on

[Rust Guide] 11.6. Controlling Test Execution - Parallel and Sequential Tests

If you find this helpful, please like, bookmark, and follow. To keep learning along, follow this series.

11.6.1 Controlling How Tests Run

Like cargo run, cargo test compiles the code and produces a binary used for testing, except that cargo test runs in test mode.

You can change cargo test’s behavior by passing arguments. If you pass no arguments, the default behavior is:

  • Run all tests in parallel
  • Capture all output when tests pass, so it is easier to read test-related output. If a test fails, the output is shown so the programmer can debug.

Command-line arguments come in two categories:

  • Arguments for cargo test itself, placed immediately after cargo test
  • Arguments for the generated executable, placed after --. For example, cargo test -- --help shows all arguments available after --, that is, all arguments for the executable.

11.6.2 Running Tests in Parallel

When running multiple tests, Rust uses multiple threads by default so tests run in parallel. This is faster, but the tests must not depend on one another, and they must not depend on shared state such as the environment, working directory, or environment variables.

If two tests depend on shared state, and one test changes that state before the other finishes, the other tests that share the same state will be affected.

If you do not want tests to run in parallel, or if you want to control exactly how many threads are used, you can use the --test-threads argument, which is passed to the binary. Put the thread count right after this argument.

For example, cargo test -- --test-threads=1 uses one thread, which means multiple tests take longer than they would in parallel. But it has an advantage: because the tests run sequentially, they are less likely to interfere with one another through shared state.

11.6.3 Showing Function Output

By default, if a test passes, Rust’s test library captures output written to standard output, such as println! output. If a test fails, the printed output is shown together with the failure message.

For example:

fn prints_and_returns_10(a: i32) -> i32 {
    println!("I got the value {a}");
    10
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn this_test_will_pass() {
        let value = prints_and_returns_10(4);
        assert_eq!(value, 10);
    }

    #[test]
    fn this_test_will_fail() {
        let value = prints_and_returns_10(8);
        assert_eq!(value, 5);
    }
}
Enter fullscreen mode Exit fullscreen mode
  • The function under test, prints_and_returns_10, prints the value it receives and then returns 10.
  • The this_test_will_pass test passes 4 to the function, so the function prints 4 and then compares the fixed return value with 10. This test succeeds.
  • The this_test_will_fail test passes 8 to the function, so the function prints 8 and then compares the fixed return value with 5. This test fails.

Test result:

$ cargo test
   Compiling silly-function v0.1.0 (file:///projects/silly-function)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.58s
     Running unittests src/lib.rs (target/debug/deps/silly_function-160869f38cff9166)

running 2 tests
test tests::this_test_will_fail ... FAILED
test tests::this_test_will_pass ... ok

failures:

---- tests::this_test_will_fail stdout ----
I got the value 8
thread 'tests::this_test_will_fail' panicked at src/lib.rs:19:9:
assertion `left == right` failed
  left: 10
 right: 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::this_test_will_fail

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--lib`
Enter fullscreen mode Exit fullscreen mode

The success case does not appear in the test output, but the failure case does: I got the value 8.

If you want successful tests to print their output too, add the flag cargo test -- --show-output. The output then looks like this:

$ cargo test -- --show-output
   Compiling silly-function v0.1.0 (file:///projects/silly-function)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.60s
     Running unittests src/lib.rs (target/debug/deps/silly_function-160869f38cff9166)

running 2 tests
test tests::this_test_will_fail ... FAILED
test tests::this_test_will_pass ... ok

successes:

---- tests::this_test_will_pass stdout ----
I got the value 4


successes:
    tests::this_test_will_pass

failures:

---- tests::this_test_will_fail stdout ----
I got the value 8
thread 'tests::this_test_will_fail' panicked at src/lib.rs:19:9:
assertion `left == right` failed
  left: 10
 right: 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::this_test_will_fail

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--lib`
Enter fullscreen mode Exit fullscreen mode

Top comments (0)