标题
- 三、控制测试流程
- 3.1 添加测试参数
- 3.2 并行或连续运行测试
- 3.3 显示函数输出
- 3.4 指定/过滤测试用例名称
- 3.5 忽略某些测试用例
- 3.6 只运行被忽略的测试
- 四、测试的组织结构
- 4.1 概念引入
- 4.2 测试私有函数
- 4.2 单元测试
- 4.3 集成测试
- 4.4 集成测试中的子模块
- 4.5 二进制crate的集成测试
三、控制测试流程
3.1 添加测试参数
- cargo test执行时并行执行所有的测试用例,并截断输出到屏幕;
- cargo test和可执行测试用例的参数都可以被改变;
- 运行cargo test时后跟cargo test和测试二进制文件的参数,中间用
--
分隔; - cargo test --help会提示 cargo test 的有关参数;
cargo test -- --help
会提示分隔符--
之后使用的参数;
3.2 并行或连续运行测试
设置测试程序并行执行数
cargo test -- --test-threads=1
3.3 显示函数输出
不只显示测试程序通过与否,还需要显示println!
的输出;
cargo test -- --show-output
3.4 指定/过滤测试用例名称
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_two_and_two() {
assert_eq!(4, add_two(2));
}
#[test]
fn add_three_and_two() {
assert_eq!(5, add_two(3));
}
#[test]
fn one_hundred() {
assert_eq!(102, add_two(100));
}
}
直接在cargo test后面加被#[test]
标记的函数名称即可;
- 红框中会运行所有包含
add_
名称的测试用例; - 蓝框中会运行
add_three_and_two
测试用例;
3.5 忽略某些测试用例
- 使用
#[ignore]
标记运行cargo test
运行时忽略的测试用例
例如为add_three_and_two添加#[ignore]属性
3.6 只运行被忽略的测试
cargo test -- --ignored
四、测试的组织结构
4.1 概念引入
测试主要分为单元测试(unit tests)与 集成测试(integration tests)
- 单元测试:与其他部分隔离的环境中测试每一个单元的代码,以便于快速而准确的某个单元的代码功能是否符合预期;
- 集成测试:对于自己的库来说完全是外部的。需要与其他外部代码一样,通过相同的方式使用代码;只测试公有接口而且每个测试都有可能会测试多个模块;
4.2 测试私有函数
- Rust 的私有性规则允许对私有函数进行测试;
pub fn add_two(a: i32) -> i32 {
internal_adder(a, 2)
}
fn internal_adder(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn internal() {
assert_eq!(4, internal_adder(2, 2));
}
}
- internal_adder函数并没有标记为pub,所以它是个私有函数;
- 它可以通过
cargo test
的运行;
4.2 单元测试
- 单元测试与要测试的代码共同存放在位于src目录下相同的文件中;
- 每个文件中创建包含测试函数的tests模块,并使用
#cfg(test)
标注模块; - 被标注为
#cfg(test)
的模块只有在cargo test
时才会编译并执行,这样就减小了二进制包的体积;
4.3 集成测试
- 目的是为了测试库的多个部分能否一起正常工作;
- 需要创建一个与src同级的tests目录;
- 只会在运行
cargo test
时编译这个目录中的文件; - 不需要
tests
目录下的任何rs文件中的任何代码标注#[cfg(test)]
创建集成测试用例: tests/integration_test.rs
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
- 需要使用
addr::
引入要测试的模块; addr
就是创建cargo项目时指定的名字;- 下图中红框部分就是integration_test.rs测试文件中的运行结果;
- 红框上面的部分是单元测试的结果;
- 红框中的部分是集成测试的结果;
- 红框下面的部分是文档测试的结果;
- 仍然可以只测试某个单独用例或使用
cargo test --test integration_test
测试integration_test.rs文件下的所有测试用例;
4.4 集成测试中的子模块
- 每一个tests目录中的文件都被编译为单独的crate;
- tests目录中的文件不能共享相同的行为;
假设
setup
函数需要被多个测试文件的测试函数调用,参考以下步骤
- 创建文件
tests/common.rs
并写入代码
pub fn setup() {
// 编写特定库测试所需的代码
}
此时运行cargo test
会看到输出
- 原意图只是希望它被其他测试文件调用而并不想要common出现在测试结果中;
- 因此做如下修改
1). 创建tests/common/mod.rs文件,这是在告诉 Rust 不要将 common 看作一个集成测试文件;
2). 将common.rs文件中的代码移动到 mod.rs中,并删除common.rs文件;
3). 此时执行cargo test
就不出出现上面的情况了;
tests 目录中的子目录不会被作为单独的 crate 编译或作为一个测试结果部分出现在测试输出中。
- 然后就可以调用
mod.rs
中的函数;
mod common;
#[test]
fn it_adds_two() {
common::setup();
assert_eq!(4, adder::add_two(2));
}
4.5 二进制crate的集成测试
- 只包含二进制可执行程序的create不能创建集成测试;
- 只有库crate才会向其他 crate 暴露了可供调用和使用的函数;
- 二进制crate只能单独运行;