Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

11.6 控制测试运行:并行和串行(连续执行)测试

11.6.1. 控制测试如何运行

cargo run一样,cargo test也会编译代码并生成用于测试的二进制文件,只不过cargo test是在测试模式下运行。

可以通过传参来改变cargo test的行为。如果不传任何参数,默认行为是:

  • 并行运行所有测试
  • 在测试通过时捕获所有输出,以便更容易阅读与测试相关的输出。如果测试失败,则会显示输出,方便程序员调试。

命令行参数分为两类:

  • 针对cargo test本身的参数,紧跟在cargo test后面
  • 针对生成的可执行文件的参数,放在--之后。例如,cargo test -- --help会显示所有能放在--之后的参数,也就是所有针对可执行文件的参数。

11.6.2. 并行运行测试

运行多个测试时,Rust默认使用多个线程,以便并行运行测试。这样更快,但这些测试彼此之间不能有依赖,也不能依赖共享状态,比如环境、工作目录或环境变量。

如果两个测试依赖共享状态,而其中一个测试在另一个完成之前改了这个状态,那么共享同一状态的其他测试就会受到影响。

如果不想并行运行测试,或者想精确控制使用多少线程,可以使用--test-threads参数,它会传给二进制文件。在这个参数后面直接写上线程数量。

例如,cargo test -- --test-threads=1使用一个线程,这意味着多个测试会比并行执行花更长时间。但它也有优点:因为测试是顺序执行的,所以它们更不容易因为共享状态而互相干扰。

11.6.3. 显示函数输出

默认情况下,如果测试通过,Rust的test库会捕获写到标准输出的内容,比如println!的输出。如果测试失败,打印出的内容会和失败信息一起显示。

看个例子:

#![allow(unused)]
fn main() {
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);
    }
}
}
  • 被测试的函数prints_and_returns_10会打印它收到的值,然后返回10。
  • this_test_will_pass测试把4传给该函数,所以函数会打印4,再把固定的返回值和10比较。这个测试会成功。
  • this_test_will_fail测试把8传给该函数,所以函数会打印8,再把固定的返回值和5比较。这个测试会失败。

一种可能的测试结果如下(默认并行执行时,test … ok / FAILED 行的顺序在不同运行之间可能不同):

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

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

failures:

---- tests::this_test_will_fail stdout ----
I got the value 8

thread 'tests::this_test_will_fail' (457588) 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`

成功的情况不会出现在测试输出中,但失败的情况会:I got the value 8

如果希望成功的测试也打印输出,加上标志cargo test -- --show-output。并行测试的结果展示顺序可能不同,这里只展示我的一次输出:

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

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

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' (461014) 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`