测试
单元测试
在Rust中,单元测试与被测试的代码存储在同一个源文件中。也就是说,对于任何给定的结构体、函数或方法,其对应的单元测试通常位于同一个源文件中。测试通常位于文件底部附近。
示例某lib.rs:
pub fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
a + b
}
// tests mod中包含测试,#[cfg(test)] attribute告诉编译器这是的单元测试模块
#[cfg(test)]
mod tests {
use super::*;
// #[test] attribute告诉编译器这个函数是一个单元测试
#[test]
fn test_add() {
assert_eq!(add(3, 4), 7);
}
}运行测试:
cargo test测试框架
- rstest - 引入了诸如fixture(用于注入测试依赖)、 parametrize(用于多值参数化测试)和async支持等功能。
- proptest - 是一个属性测试框架。它允许测试代码的某些属性是否对任意输入都成立,如果发现失败,会自动找到重现问题的最小测试用例。用来进行随机测试
parameterizedtest-caseassert2
单元测试覆盖率
支持单元测试覆盖率显示:
- cargo tarpaulin: 运行测试并分析你的Rust代码并提供代码覆盖率数据
- cargo watch: 每次我们保存文件时,运行
cargo tarpaulin - coverage gutters: 在VSCode中显示覆盖的代码行
cargo install cargo-tarpaulincargo tarpaulin命令的更多参数详见。
cargo tarpaulin --out Lcov --output-dir target/tarpaulin上面的命令在target/tarpaulin目录里生成了lcov.info文件。
CMD+Shift+P输入Coverage Gutters: Watch输入后,会自动发现lcov.info文件,并在项目源码中显示测试覆盖率。
安装cargo-watch:
Cargo Watch监视你的项目的源代码是否有变化,并在变化发生时运行Cargo命令。
cargo install cargo-watchcargo watch -x 'tarpaulin --out Lcov --output-dir target/tarpaulin'性能优化:
cargo watch -x 'tarpaulin --out Lcov --output-dir target/tarpaulin' -w src集成测试
https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html
集成测试是从公共接口对单个模块或组进行测试。
在Rust中与单元测试不同,集成测试位于主源代码树之外。Rust将集成测试视为单独的包,它们只能访问公开导出的函数和结构。
单元测试一次只测试一个独立的模块:它们很小,可以测试私有代码。集成测试位于你的 crate 外部,并且像任何其他代码一样只使用其公共接口。它们的目的是测试库的许多部分是否能正确地协同工作。Cargo 会在 src 旁边的 tests 目录中查找集成测试。
文件src/lib.rs:
// Define this in a crate called `adder`.
pub fn add(a: i32, b: i32) -> i32 {
a + b
}文件tests/integration_test.rs:
#[test]
fn test_add() {
assert_eq!(adder::add(3, 2), 5);
}执行测试:
$ cargo test
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target/debug/deps/integration_test-bcd60824f5fbfe19
running 1 test
test test_add ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered outtests目录中的每个Rust源文件都被编译成一个单独的crate。为了在集成测试之间共享一些代码,我们可以创建一个包含公共函数的模块,并在测试中导入和使用它。
文件tests/common/mod.rs:
pub fn setup() {
// some setup code, like creating required files/directories, starting
// servers, etc.
}文件tests/integration_test.rs:
// importing common module.
mod common;
#[test]
fn test_add() {
// using common code.
common::setup();
assert_eq!(adder::add(3, 2), 5);
}创建模块为tests/common.rs也可以工作,但不推荐这样做,因为测试运行器会将该文件视为测试crate并尝试运行其中的测试。
测试框架
- assert_cmd 简化CLI的集成测试过程,包括:查找要测试的 crate 的二进制文件;断言程序运行的结果。
- rexpect
文档测试
记录Rust项目的主要方式是通过对源代码添加注释。文档注释采用CommonMark Markdown规范编写,并支持其中的代码块。Rust 注重代码的正确性,因此这些代码块会被编译并用作文档测试。
模糊测试(Fuzz testing)
模糊测试使用随机生成的数据来测试代码,这些数据不一定有效。模糊测试在安全敏感的环境中尤其受欢迎,在这种情况下,希望了解当代码被滥用时会发生什么。