Rust项目中的单元测试和集成测试
- 单元测试与集成测试
- 什么是单元测试
- 什么是集成测试
- Rust中的单元测试
- Rust中单元测试的组织化
- Rust单元测试的语法细节
- Rust中的集成测试
- Rust中集成测试的组织化
- Rust中集成测试的语法细节
- Rust测试的一些值得注意的点
- 总结
单元测试与集成测试
测试对于每一个项目都至关重要,开发者一般都无法保证代码的完全正确,因为这是一个无法证实的问题,只能充分证伪,也就是用足够的测试case覆盖,来让故障率降低。一般来讲,对于针对于开发者自己编写的测试来说,分为单元测试和集成测试。
什么是单元测试
单元测试(unit test),即以开发者的角度,与主程序代码关系密切的测试,简单来说,单元测试一般包含在源代码文件夹中,通过对程序代码内的函数单元直接调用,在通过Err/panic/assert等的判断方式判定结果,使用方式如开发者的使用方式一般。
什么是集成测试
集成测试(intergration test),既以用户的角度,通常在源代码之外的文件夹内,调用pub函数,通过函数行为产生的结果判断正确性,举个例子,如果开发者实现的是一个库,集成测试就更加接近库使用方的调用方式。
Rust中的单元测试
Rust中单元测试的组织化
单元测试与源代码关系紧密,一般情况下,在实际项目使用中,直接在源码处添加tests模块,并将想要测试的内容放入模块之中,在cargo test 时直接运行即可,这样的好处主要是一目了然,并将测试与代码紧密关联,减少遗漏概率,同时也降低了新手接入项目的难度。
Rust单元测试的语法细节
代码示例:
pub fn add(left: usize, right: usize) -> usize {left + right
}#[cfg(test)]
mod tests {use super::*;#[test]fn it_works() {let result = add(2, 2);assert_eq!(result, 4);}
}
#[cfg(test)]: 这里提到的最主要的作用便是和cargo build区分开,也就是,以此标记的模块代码只有在执行cargo test时候才会被编译,而在build时候则会被忽略,开发者可以尝试去掉#[cfg(test)] ,再执行cargo build 编译会发生什么。
#[test]: 这个宏是cargo test 能找到测试函数并执行的关键入口,尽管mod tests 看起来也很象是个限制,但是如果开发者将它换个名字会发现什么问题都不会发生。mod 名字tests仅是一种约定俗成。
use super:😗;:提到这全部的引入,不得不提到Rust提供了一种与其他语言不同的,独特的能力,就是可以在单元测试中测试私有函数,Rust仅提供这样的能力,但是不会强制开发者一定对私有函数进行测试。
Rust中的集成测试
Rust中集成测试的组织化
集成测试更贴近于用户使用,集成测试在Rust中也默认放置在src所在同级目录下,名称为tests,既于源代码割裂开,以用户使用的角度测试每一个开放性接口,亦或是在网络服务器编程中提供的Api,最后通过行为判定结果的正确与否。
PS D:\workspace\Rust-Project\testmodule\adder> tree
D:.
├─src
└─tests
目录结构如上,与单元测试不同,集成测试的文件夹名称固定,Rust通过此来进一步执行测试内容,如果将文件夹名称改变,开发者将会注意到,集成测试代码并不会被执行。
Rust中集成测试的语法细节
与单元测试中并无二致。
Rust测试的一些值得注意的点
- 通常情况下, 测试中判定测试方法执行正确与否包括三种方式,assert!,panic!,Err.
- assert 在claim一文中有所提及,建议开发者使用更方便的包将信息带出。
- panic!并不是只能被判定失败,如使用#[should_panic] 则可以在panic处表示测试通过。
- Rust测试中,默认的,被判定正确执行的函数中的输出并不会输出到指定位置,如果开发者需要输出人为检查,可以运行:
cargo test -- --show-output
- #[ignore] 在标记测试方法后,如果开发者需要忽略一些测试函数,便可执行:
cargo test -- --ignored
- Rust的测试中,开发者还可以根据需要,如在自测时:
- 仅仅需要执行一个相关的测试,可以指定名称:
cargo test funcxxxx
- 需要指定某一系列的相关测试:
cargo test prefix //prefix为函数前缀,所以test方法的命名也需要合理
- 默认 情况下,rust的测试是多线程的,独立分割的,所以在编写测试用例时需要注意共有变量的同步性,如果测试需要一定的顺序性开发者也可以指定线程数量为1:
cargo test -- --test-threads=1
总结
测试很必要也很重要,在日常开发中,抑或是自己的兴趣开发中,编写测试代码对于迭代下的代码鲁棒性至关重要。
“知行合一是一件很难做到的事”