bigywater.tech
Rust · 157

单元测试与集成测试

Rust 自带测试框架,但「单元测试放哪、集成测试能看到什么、输出什么时候显示、测试是不是并行」这些细节不看真实输出很容易记错。这篇搭一个小库,把 cargo test 的各类测试和开关一个个跑出来。

3 类
cargo test 运行的测试种类:单元、集成、文档
E0603
集成测试访问私有函数的错误码
0.41 对 0.83 s
测试并行与 --test-threads=1 的汇总耗时

三类测试

实测 · 本机执行输出
       Running unittests src/lib.rs (<实验目录>/target/debug/deps/calc-ae581424acae7e17)
       Running tests/api.rs (<实验目录>/target/debug/deps/api-db5bac28d6805c15)
       Running tests/second.rs (<实验目录>/target/debug/deps/second-191b2db47871f4f4)
     Doc-tests calc
  running 5 tests
  test tests::add_works ... ok
  test tests::can_test_private ... ok
  test tests::slow_test ... ignored, 很慢
  test tests::prints_something ... ok
  test tests::div_by_zero - should panic ... ok
  test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s
  running 1 test
  test public_api ... ok
  test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s
  running 1 test
  test div_ok ... ok
  test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
  running 0 tests
  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

文档测试见Doc Test;性能测试见Benchmark。

可见性

实测 · 本机执行输出
  error[E0603]: function `secret` is private
    |           ^^^^^^ private function
  For more information about this error, try `rustc --explain E0603`.

过滤与忽略

实测 · 本机执行输出
  --list 列出的单元测试: ['tests::add_works: test', 'tests::can_test_private: test', 'tests::div_by_zero: test', 'tests::prints_something: test', 'tests::slow_test: test']
  按名字过滤 add:
    test tests::add_works ... ok
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 4 filtered out; finished in 0.00s
  --ignored 只跑被忽略的:
    test tests::slow_test ... ok
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 4 filtered out; finished in 0.30s
  默认(被忽略的显示为 ignored):
    test tests::add_works ... ok
    test tests::slow_test ... ignored, 很慢
    test tests::can_test_private ... ok
    test tests::prints_something ... ok
    test tests::div_by_zero - should panic ... ok
    test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s

失败与输出捕获

实测 · 本机执行输出
  cargo test --test api 退出码 101
       Running tests/api.rs (<实验目录>/target/debug/deps/api-db5bac28d6805c15)
  error: test failed, to rerun pass `--test api`
  running 2 tests
  test public_api ... ok
  test failing_example ... FAILED
  failures:
  ---- failing_example stdout ----
  thread 'failing_example' (7546628) panicked at tests/api.rs:3:32:
  assertion `left == right` failed: 故意失败的断言
    left: 2
   right: 3
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  failures:
      failing_example
  test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
  --nocapture 时: ['这行 stdout 默认被捕获,只有失败或 --nocapture 才显示']
  不加 --nocapture(通过的测试): []

断言失败时的 panic 见panic!、unwrap 与 expect。

并行

实测 · 本机执行输出
  默认并行               ['同时运行的 work() 最多 4 个']  测试汇总行里的 finished in 0.41 s
  --test-threads=1   ['test zz_report ... 同时运行的 work() 最多 1 个']  测试汇总行里的 finished in 0.83 s

并行用的是线程,线程基础见线程创建与 Join。

分步演示

单元测试与集成测试
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / rustc 1.98.1(brew)/ cargo 1.98.1;单个文件用 rustc 直接编译,需要依赖时用 cargo(经代理从 crates.io 下载);计时用 std::time::Instant,数字每次运行会有小幅抖动
    • 没有验证:--format json / JUnit 报告(需要 nightly)、测试里启动子进程或网络服务的隔离、#[test] 返回 Result 的行为、dev-dependencies 对测试的影响、cargo nextest 的差异、测试覆盖率工具
    京ICP备2026067502号-1京公网安备11010502063487号