Rust中的模块测试是通过内置宏、特殊属性和cargo基础设施直接集成在语言中的。历史上,在C和其他一些语言中,测试是外部附加的,这导致生产代码和测试接口之间的不一致。在Rust中,测试与主代码在同一环境中编译和运行,从而消除了"仅在测试中工作"的问题。
问题:测试可能会减慢构建速度,可能不够信息丰富或组织不当;此外,隔离不佳的测试会妨碍代码的维护和可读性。
解决方案:测试被编写为带有属性#[test]的特殊函数,位于模块mod tests之内。所有测试代码仅在使用cargo test命令时编译和运行,生产构建中则被排除。使用像assert_eq!、should_panic和setup方法可以提高测试的效率和洁净度。
代码示例:
pub fn add(a: i32, b: i32) -> i32 { a + b } #[cfg(test)] mod tests { use super::*; #[test] fn test_add() { assert_eq!(add(2, 2), 4); } }
关键特性:
cargo test构建时编译,不会进入发布二进制文件测试必须放在嵌套模块mod tests中吗?
不必,但这样做是为了隔离测试以及防止测试代码泄露到发布中。还可以帮助使用#[cfg(test)]。
可以仅对特定模块/文件运行测试吗?
是的,可以通过cargo test 测试名指定测试名或路径。
私有函数会被测试吗?
会的,如果测试模块在同一文件内定义并使用use super::*;,测试可以访问该文件中的所有内部函数。
测试与主代码混在一起,没有隐藏在#[cfg(test)]中,使用全局变量进行初始化。
优点:
缺点:
测试封装在嵌套模块中,使用setup函数和assert_eq!宏进行检查。
优点:
缺点: