在Rust中进行集成测试
集成测试是一种独立于代码的测试方式,进行集成测试时,相当于从外部调用库或运行程序,它常用于测试项目整体,而非独立的单元。
集成测试的代码放在根目录下的tests
目录中,目录下的每个文件都是独立的包,这意味着测试项目时,就好像使用外部的包一样,需要独立导入,且每个测试文件之间也是独立的。
准备
一些库经常在集成测试中使用,在cargo.toml中加入这些开发依赖:
1 | [dev-dependencies] |
截至文章更新时间,这里列出的版本号以及下文的用法均对应最新版本。
使用tempfile
创建临时目录和文件
我们在测试时常常需要使用一些文件与目录,使用临时文件会比使用根目录下指定的文件更好。tempfile
包提供了生成临时文件的功能。
1 | use tempfile::{tempfile, tempdir}; |
使用assert_cmd
测试可执行程序
集成测试中常常需要直接测试可执行程序而非某个库功能,此时可以使用assert_cmd
。
假定我们构建的可执行程序的文件名为hello.exe
,使用cargo
运行需要的指令为cargo run --bin hello
。
使用assert_cmd
中的Command::cargo_bin("hello")
即可达到同样的效果。
控制测试环境
我们常常需要在测试时指定一些环境变量或标准输入内容。Command
结构体提供了一些方法,可以定制运行环境。
1 | use asser_cmd::Command; |
使用Assert
与Predicate
判断测试结果
我们需要获取程序运行的结果并测试是否符合预期,这时可以对Command
调用assert()
方法获取Assert
对象,通过Assert
来测试结果。
例如,我们编写了一个从标准输入中读取一个数字,并输出它的平方的程序,可以使用如下方法进行测试。
1 | use assert_cmd::Command; |
stdout
方法的签名为:
1 | pub fn stdout<I, P>(self, pred: I) -> Self |
Predicate
是predicate_core
中规范的trait
,当我们传入"400"
时,表示输出内容与其完全匹配。
predicates
库包含许多功能强大的Predicate
,例如部分匹配,假定我们想要测试使用-V
参数后,输出的内容中是否包含程序版本号,我们可以编写如下测试:
1 | use assert_cmd::Command; |
除此之外,还常用Assert
判断程序是否正确退出。
1 | Command::cargo_bin("bin_fixture") |
手动判断测试结果
当我们需要对输出进行复杂的判断时,Assert
与Predicate
可能无法满足我们的需求。我们可以在Command
上调用output
方法获取Ouput
对象,这个对象保存了程序的stdout
和stderr
输出,获取输出后可以手动编写判断语句。
1 | let mut output = Command::cargo_bin(env!("CARGO_PKG_NAME")) |
基准测试
nightly的Rust自带cargo bench
基准测试功能,但自带的基准测试事实上已经被deprecated了,不会出现在stable中。更推荐使用criterion
库进行基准测试。
1 | pub fn criterion_benchmark(c: &mut Criterion) { |