十、Rust 程序测试
1. Rust 中的测试
-
Rust 中,测试函数就是一个带有
test属性注解的函数或方法// 创建一个 lib 项目时,默认生成的一个模板 #[cfg(test)] mod tests { #[test] // 表明这是一个测试函数 fn it_works() { let result = 2 + 2; assert_eq!(result, 4); // 一个断言宏 } } -
在运行测试用例的过程中,当测试函数中出现 panic 时,测试就失败了
-
Rust 内置的测试模块,还会运行文档注释里的示例代码,这是其他很多编程语言的测试工具所不具备的能力
-
在了解用于测试的内置工具之前,需要了解一个概念:可被比较测试的值
- 可被比较的值必需实现了
PartialEq和Debugtrait
- 可被比较的值必需实现了
-
用于测试的相关宏
assert!(success: bool)- 判断传入的布尔值是否为 true,如果为 true 则测试通过
assert_eq!($left:expr, $right:expr $(,)?)- 两个参数对应了两个表达式
- 判断两个表达式的结果是否相等。如果相等,则测试通过;反之,则测试不通过
- 如果测试不通过,会打印出两个表达式的值
assert_ne!($left:expr, $right:expr $(,)?)- 两个参数对应了两个表达式
- 判断两个表达式的结果是否不等。效果与
assert_eq!相反,如果不等,则测试通过;反之,则测试不通过
-
用于测试的相关属性
-
#[should_panic]-
用于测试
panic的结果是否正确// 来自官方教程的一个示例 pub struct Guess { value: i32, } impl Guess { pub fn new(value: i32) -> Guess { if value < 1 || value > 100 { panic!("Guess value must be between 1 and 100, got {}.", value); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "Guess value must be less than or equal to 100")] fn greater_than_100() { Guess::new(200); } }
-
-
2. 运行测试用例
-
命令:
cargo test- 这个命令接收两个部分的参数,这两个部分的参数都以
--开头,如果第一个参数没有,仍然要用这个符号占位- 命令格式:
cargo test --<test_case_name> --<param2[=some_value]> - 示例命令:
cargo test -- --test-threads=1 - 第一部分:传递给
cargo test命令本身的参数- 这个示例里没有,通常是指定要运行的测试用例的名称或期望测试的模块的名称
- 第二部分:传递给生成的测试二进制文件的参数
- 这个示例里是
--test-threads=1
- 这个示例里是
- 命令格式:
- 第一部分的参数
- 通常用于指定测试用例的名称或测试的模块名称
- 第二部分的参数
--test-threads=<number>控制测试线程的数量--nocapture控制是否显示成功的测试用例的print!/println!输出- 带上这个参数时,会显示;反之,不显示
--ignored控制运行的测试用例的忽略类型- 带上这个参数时,只会运行被忽略的测试用例 (带
#[ignore]) - 不带这个参数时,只会运行未被忽略的测试用例 (不带
#[ignore])
- 带上这个参数时,只会运行被忽略的测试用例 (带
- 这个命令接收两个部分的参数,这两个部分的参数都以
-
注意事项
- 多个测试用例是多线程并行运行的,一定要注意这些测试用例之间不要互相依赖,也不要有互相冲突的操作 (如文件读写)
- 测试所在的模块也是测试名称的一部分,所以可以通过模块名来运行一个模块中的所有测试
-
局部测试
- 利用第一个参数来指定期望测试的测试用例或期望测试的模块
cargo test <test_fn_name>仅运行 test_fn_name 对应的测试用例cargo test <test_filte>运行所有名称中包含 test_filte 的测试用例
-
忽略测试用例
#[ignore]- 只允许被忽略的测试用例:
cargo test -- --ignored
3. 组织测试用例
- 合理组织测试用例,将能最大程度上提高测试代码的可读性、可测试性和可维护性
- 单元测试
- 存放目录:与它们要测试的代码的同一个目录
- 规范要求:在每一个文件中创建包含测试函数的
tests模块,并使用#[cfg(test)]标注cfg: configuration
- 集成测试
- 存放目录:tests 目录,与 src 目录同级
- 可以创建任意多个测试文件,“Cargo 会将每一个文件当作单独的 crate 来编译”
- 不需要将 tests/integration_test.rs 中的任何代码标注为
#[cfg(test)] - 运行指定的集成测试文件:
cargo test --test <file_in_tests> - 注意事项
- tests 目录中的文件不能像 src 中的文件那样共享相同的行为
- 存放目录:tests 目录,与 src 目录同级