Skip to main content
9 测试

9 测试

•1 min•120 words

测试的泛式

测试输入+测试方法+结果断言

无论是单元测试还是集成测试,都拥有一样的测试泛式。我们需要测试的只是中间的环境,但是在测试之前需要准备测试数据以及预期结果。

单元测试

rust的单元测试直接写在源码中,通过属性标记

rust可以将测试代码直接写在源文件中,通常我们会创建额外的模块来收纳测试函数。
只在运行cargo test的时候编译运行测试代码。

pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}

#[cfg(test)]属性标记,条件编译,这样标志之后,被标记的模块只会在运行测试的时候编译。不会被编译进debug以及发型版。

#[test]属性标记测试方法,函数必须没有参数,返回值必须是 ()或Result<(), E>。
被标记的测试方法,将被编译进一个测试用的二进制crate中用于测试。

Summary

我们可以用过测试函数的全路径匹配来执行指定路径的测试函数,所有路径包含次字符串的测试函数都将执行。

cargo test <匹配关键词>
# 或者将匹配项放在 -- 后面
cargo test -- <匹配关键词> 
命令参数分段

cargo test以及cargo的其他命令都有命令参数分段的设定。我们需要对cargo传入一些参数,也需要对cargo调用的二进制运行项目一些运行参数,这两部分参数需要同时进行传递,所以为了区分,将cargo的命令参数放在前面,而后面对要调用的二进制程序的参数放在 — 参数之后(实际上我们知道2_python解释器)

忽略测试函数,以及包含忽略。
打印测试输入。

Summary

断言结果

常见的断言

assert!(true或者false)
assert_eq!(left,right) 判断是否相等

检测Result<(),E>,检测Panic!

panic!判断,

#[should_panic]
当判断一个函数应该报panic的时候,可以在函数头上标注#[should_panic]

判断模式匹配

match!(模式1,模式2)
这个宏进行模式匹配并返回bool

条件编译

只有满足这些条件,这些代码才会被编译。

#[cfg(test)] 在测试环境
#[cfg(target_os = "android")] 在android编译
#[cfg(not(target_os = "android"))] 在非android编译

控制测试运行

并发执行测试函数,以及设置并发数量。

集成测试

集成测试:只具有外部访问权限的测试程序

只能调用一部分库中的公有 API。集成测试的目的是测试库的多个部分能否一起正常工作。

Rust设计了标准的集成测试范式

在项目根目录创建一个 tests 目录,与 src 同级。Cargo 会去寻找这个目录中的集成测试文件。

自动分crate,每个文件隔离开

集成测试目录中的文件,自动被编译为单独的crate,也就是Cargo默认让我们以文件为单位写集成测试。

需要将库引入到每个测试 crate 的作用域中,就像其他外部使用者一样,这点区别于单元测试,因为单元测试是直接在源码内部的测试,无须导入。

不需要将 tests/integration_test.rs 中的任何代码标注为 #[cfg(test)] 。 tests 文件夹在 Cargo 中是一个特殊的文件夹,Cargo 只会在运行 cargo test 时编译这个目录中的文件。

测试顺序:单元->集成->文档测试

执行cargo test后,会依次执行单元测试、集成测试、文档测试。
注意如果一个部分的任何测试失败,之后的部分都不会运行。

避免出现因为一个错误导致集成测试连带失败的问题,我们应该先解决单元测试再解决集成测试问题。

Cite
Summary
如何在测试目录编写共用crate lib而让其不作为测试crate呢?

Rust给集成测试弄了特殊的语法,可以使用旧的模块语法来表示多crate共享的模块。
实际上并非共享模块,而是让“共享模块”的代码分别编译进每个测试二进制文件中,来实现类似共享的效果。

集成测试只能适用于“库crate”,而不适用于“二进制crate”

只有库 crate才会向其他 crate 暴露了可供调用和使用的函数;二进制 crate 只意在单独运行。
但是我们可以让二进制crate调用lib crate来实现,我们对lib crate进行测试就行了,这就是许多 Rust 二进制项目使用一个简单的 src/main.rs 调用 src/lib.rs 中的逻辑的原因之一。

性能测试

性能测试虽然官方推出了nightly版本,但是其功能还是不如专用性能测试工具 criterion。

安装之后cargo通过 cargo bench启动,寻找bench目录下的性能测试crate。

通过cargo.toml配置性能测试用例名,通过名字定位文件位置。