1、控制测试如何运行
改变cargo test的行为:添加命令行参数
默认行为:
并行运行
所有测试
捕获(不显示)所有输出,使读取与测试结果相关的输出更容易。
命令行参数:
针对cargo test的参数:紧跟cargo test后
针对测试可执行程序:放在--之后
显示帮助:cargo test --help
显示可以使用在两个横线之后的参数:cargo test -- --help
2、并行/连续运行测试
并行运行测试
运行多个测试:默认使用多个线程并行运行。
运行快
确保测试之间:
-不会互相依赖
-不依赖于某个共享状态(环境、工作目录、环境变量等等)
--test-threads参数
传递给二进制文件
不想以并行方式运行测试,或想对线程数进行细粒度控制
可以使用--test-threads参数,后边跟着线程的数量
例如: cargo test -- --test-threads=1
显式函数输出
默认,如测试通过,Rust的 test库会捕获所有打印到标准输出的内容。
例如,如果被测试代码中用到了println!:
如果测试通过:不会在终端看到println!打印的内容
如果测试失败:会看到printIn!打印的内容和失败信息
fn prints_and_returns_10(a:i32)->i32 {
println!("I got the value {}",a);
10
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn this_test_will_pass() {
let value = prints_and_returns_10(4);
assert_eq!(10,value);
}
#[test]
fn this_test_will_fail() {
let value = prints_and_returns_10(8);
assert_eq!(5,value);
}
}
上面的代码直接运行cargo test通过的函数不会打印pri的内容,失败的才会打印,如果想通过的也打印pri的内容,我们可以加两个参数
cargo test -- --show-output
这样通过的也能打印了
3、按名称运行测试
按名称运行测试的子集
选择运行的测试:将测试的名称(一个或多个)作为cargo test的参数
fn add_two(a:i32)->i32 {
a+2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_two_add_two() {
let value = add_two(2);
assert_eq!(4,value);
}
#[test]
fn add_three_add_two() {
let value = add_two(3);
assert_eq!(5,value);
}
#[test]
fn one_hundred() {
let value = add_two(100);
assert_eq!(102,value);
}
}
cargo test one_hundred
我们使用cargo test 【测试函数的名称】就可以控制测试哪一个函数了
运行多个测试:指定测试名的一部分(模块名也可以)
cargo test add
我们是前缀是add的函数运行就能成功运行前面两个测试函数
cargo test tests
也可以使用模块名tests来进行测试
忽略测试
忽略某些测试,运行剩余测试
ignore属性( attribute)
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(4,2 + 2);
}
#[test]
#[ignore]
fn expensive_test() {
assert_eq!(5,2 + 3);
}
}
运行cargo test 就会忽略第二个测试函数
如果我想单独运行第二个被忽略的函数要怎么弄呢?我们可以直接运行
cargo test -- --ignored
4、测试的组织
测试的分类
Rust 对测试的分类:
单元测试
集成测试
单元测试:
小、专注
一次对一个模块进行隔离的测试
可测试private接口
集成测试:
在库外部。和其它外部代码一样使用你的代码
在库外部。和其它外部代码一样使用你的代码
只能使用public接口
可能在每个测试中使用到多个模块
#[cfg(test)]标注
tests模块上的#[cfg(test)]标注:
一只有运行cargo test才编译和运行代码
运行cargo build 则不会
集成测试在不同的目录,它不需要#[cfg(test)]标注
cfg: configuration(配置)
一告诉Rust下面的条目只有在指定的配置选项下才被包含
配置选项test:由Rust提供,用来编译和运行测试。
只有cago test才会编译代码,包括模块中的helper函数和#[test]标注的函数
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(4,2 + 2);
}
}
测试私有函数
Rust允许测试私有函数
pub fn add_two(a:i32)->i32 {
interbal_adder(a,2)
}
fn interbal_adder(a:i32,b:i32)->i32 {
a+b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(4,interbal_adder(2,2));
}
}
5、集成测试
在Rust里,集成测试完全位于被测试库的外部
目的:是测试被测试库的多个部分是否能正确的一起工作
集成测试的覆盖率很重要
tests目录
创建集成测试: tests目录
tests目录下的每个测试文件都是单独的一个crate
需要将被测试库导入
无需标注#[cfg(test)],tests目录被特殊对待
只有cargo test,才会编译tests目录下的文件
lib.rs:
pub fn add_two(a:i32)->i32 {
interbal_adder(a,2)
}
fn interbal_adder(a:i32,b:i32)->i32 {
a+b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(4,interbal_adder(2,2));
}
}
tests目录下的测试文件intregration_test.rs:
use demo;
#[test]
fn it_adds_two() {
assert_eq!(4,demo::add_two(2))
}
运行cargo test即可
运行指定的集成测试
运行一个特定的集成测试:cargo test 函数名
运行某个测试文件内的所有测试: cargo test --test 文件名
another_test.rs:
use demo;
#[test]
fn it_really_adds_two() {
assert_eq!(4,demo::add_two(2))
}
运行:
cargo test --test intregration_test
这样就只会运行intregration_test文件下的集成测试
集成测试中的子模块
tests 目录下每个文件被编译成单独的crate
这些文件不共享行为(与src下的文件规则不同)
我们在tests目录下建立一个字目录common,这样我们来运行的时候common下的mod.rs就不会当成一个集成测试的文件了
那么我们如何在intergration_test文件上运行呢?
use demo;
mod common;
#[test]
fn it_adds_two() {
common::setup();
assert_eq!(4,demo::add_two(2))
}
针对binary crate的集成测试
如果项目是 binary crate,只含有src/main.rs没有src/lib.rs:
不能在tests 目录下创建集成测试
无法把main.rs的函数导入作用域
只有library crate 才能暴露函数给其它crate 用
binary crate意味着独立运行