rust第四篇,主要讲rust测试
单元测试与集成测试
与单元测试的同吃同住不同,集成测试的代码是在一个单独的目录下的。由于它们使用跟其它模块一样的方式去调用你想要测试的代码,因此只能调用通过 pub
定义的 API
,这一点与单元测试有很大的不同。
如果说单元测试是对代码单元进行测试,那集成测试则是对某一个功能或者接口进行测试,因此单元测试的通过,并不意味着集成测试就能通过:局部上反映不出的问题,在全局上很可能会暴露出来。
一个标准的 Rust 项目,在它的根目录下会有一个 tests
目录,大名鼎鼎的 ripgrep
也不能免俗。
没错,该目录就是用来存放集成测试的,Cargo 会自动来此目录下寻找集成测试文件。我们可以在该目录下创建任何文件,Cargo 会对每个文件都进行自动编译,但友情提示下,最好按照合适的逻辑来组织你的测试代码。
首先来创建一个集成测试文件 tests/integration_test.rs
,注意,tests
目录一般来说需要手动创建,该目录在项目的根目录下,跟 src
目录同级。然后在文件中填入如下测试代码:
1 | use adder; |
首先与单元测试有所不同,我们并没有创建测试模块。其次,tests
目录下的每个文件都是一个单独的包,我们需要将待测试的包引入到当前包的作用域后: use adder
,才能进行测试 。大家应该还记得包和模块章节中讲过的内容吧?在创建项目后,src/lib.rs
自动创建一个与项目同名的 lib
类型的包,由于我们的项目名是 adder
,因此包名也是 adder
断言
在编写测试函数时,断言决定了我们的测试是通过还是失败,它为结果代言。在前面,大家已经见识过 assert_eq!
的使用,下面一起来看看 Rust 为我们提供了哪些好用的断言。
在正式开始前,来看看常用的断言有哪些:
assert!
,assert_eq!
,assert_ne!
, 它们会在所有模式下运行debug_assert!
,debug_assert_eq!
,debug_assert_ne!
, 它们只会在Debug
模式下运行
基准测试benchMark
几乎所有开发都知道,如果要测量程序的性能,就需要性能测试。
性能测试包含了两种:压力测试和基准测试。前者是针对接口 API,模拟大量用户去访问接口然后生成接口级别的性能数据;而后者是针对代码,可以用来测试某一段代码的运行速度,例如一个排序算法。
而本文将要介绍的就是基准测试 benchmark
,在 Rust 中,有两种方式可以实现:
- 官方提供的
benchmark
- 社区实现,例如
criterion.rs
官方benchMark
官方提供的测试工具,目前最大的问题就是只能在非 stable
下使用,原因是需要在代码中引入 test
特性: #![feature(test)]
。
开始正式编写 benchmark
代码。首先,将 src/lib.rs
中的内容替换成如下代码
1 |
|
可以看出,benchmark
跟单元测试区别不大,最大的区别在于它是通过 #[bench]
标注,而单元测试是通过 #[test]
进行标注,这意味着 cargo test
将不会运行 benchmark
代码
cargo test
直接把我们的 benchmark
代码当作单元测试处理了,因此没有任何性能测试的结果产生。
对此,需要使用 cargo bench
命令:
1 | cargo bench |
官方 benchmark
有两个问题,首先就是不支持 stable
版本的 Rust,其次是结果有些简单,缺少更详细的统计分布。
因此社区 benchmark
就应运而生,其中最有名的就是 criterion.rs
,它有几个重要特性:
- 统计分析,例如可以跟上一次运行的结果进行差异比对
- 图表,使用
gnuplots
展示详细的结果图表
首先,如果你需要图表,需要先安装 gnuplots
,其次,我们需要引入相关的包,在 Cargo.toml
文件中新增 :
1 | [dev-dependencies] |
接着,在项目中创建一个测试文件: $PROJECT/benches/my_benchmark.rs
,然后加入以下内容:
1 | use criterion::{black_box, criterion_group, criterion_main, Criterion}; |
最后,使用 cargo bench
运行并观察结果