github地址:https://github.com/bradyjoestar/rustnotes
pdf下载链接:https://github.com/bradyjoestar/rustnotes/blob/master/Rust%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.pdf
参考:
https://rustcc.gitbooks.io/rustprimer/content/ 《RustPrimer》
https://kaisery.github.io/trpl-zh-cn/ 《Rust程序设计语言-简体中文版》
第九章 测试与评测
在rust中内部构建了测试和评测模块,虽然目前bench模块仍然在nightly channel。
需要手动将rust切换到nightly版本,通过以下命令:
rustup default nightly
作为软件工程质量保障体系的重要一环,测试是应该引起我们充分注意并重视的事情。前面说过,Rust 语言的设计集成了最近十多年中总结出来的大量最佳工程实践,而对测试的原生集成也正体现了这一点。很大程度借鉴了golang的部分内容。
Rust 的测试特性按精细度划分,分为 3 个层次:
1.函数级;主要通过#[test] 标识
2.模块级;主要通过#[cfg(test)]标志。
3.工程级;例如黑盒测试,放于test目录下。
另外,Rust 还支持对文档进行测试。
一个项目中路径如下:
之前提到过的Cargo.toml补充:
cargo.toml和cargo.lock文件总是位于项目根目录下。
源代码位于src目录下。
默认的库入口文件是src/lib.rs。
默认的可执行程序入口文件是src/main.rs。
其他可选的可执行文件位于src/bin/*.rs(这里每一个rs文件均对应一个可执行文件)。
外部测试源代码文件位于tests目录下。
示例程序源代码文件位于examples。
基准测试源代码文件位于benches目录下。
9.1 函数级测试
当我们创建一个空的库项目时,打开src/lib.rs文件,可以看到如下代码:
#[test]
fn it_works() {
// do test work
}
Rust 中,只需要在一个函数的上面,加上 #[test] 就标明这是一个测试用的函数。
有了这个属性之后,在使用cargo build编译时,就会忽略这些函数。使用 cargo test 可以运行这些函数。类似于如下效果:
$ cargo test
Compiling adder v0.0.1 (file:///home/you/projects/adder)
Running target/adder-91b3e234d4ed382a
running 1 test
test it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
此外,可以使用的属性还有:
[ignore]
[should_panic]
9.2 模块级测试
有时,我们会组织一批测试用例,这时,模块化的组织结构就有助于建立结构性的测试体系。Rust 中,可以类似如下写法:
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::add_two;
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
}
也即在 mod 的上面写上 #[cfg(test)] ,表明这个模块是个测试模块。一个测试模块中,可以包含若干测试函数,测试模块中还可以继续包含测试模块,即模块的嵌套。
如此,就形式了结构化的测试体系,甚是方便。
9.3工程级测试(黑盒集成测试)
函数级和模块级的测试,代码是与要测试的模块(编译单元)写在相同的文件中,一般做的是白盒测试。工程的测试,一般做的就是黑盒集成测试了。
我们看上图截图工程的目录,在这个目录下,有一个 tests 文件夹。
extern crate rusttest;
#[test]
fn block_box_test() {
assert_eq!(4, rusttest::add_two(2));
}
这里,比如,我们 src 中,写了一个库,提供了一个 add_two 函数,现在进行集成测试。
首先,用 extern crate 的方式,引入这个库,由于是同一个项目,cargo 会自动找。引入后,就按模块的使用方法调用就行了,其它的测试标识与前面相同。
9.4 基准测试
单元测试是用来校验程序的正确性的,然而,程序能正常运行后,往往还需要测试程序(一部分)的执行速度,这时,就需要用到性能测试。 通常来讲,所谓性能测试,指的是测量程序运行的速度,即运行一次要多少时间(通常是执行多次求平均值)。Rust参照go实现了这部分内容。
推荐基准测试专门写在benches下,否则容易编译失败,在使用stable channel时。
例子如下:
#![feature(test)]
extern crate test;
extern crate rusttest;
#[cfg(test)]
mod testbinwen {
use rusttest::add_two;
use test::Bencher;
#[bench]
fn bench_add_two(b: &mut Bencher) {
b.iter(|| add_two(2));
}
}
评测函数fn bench_add_two(b: &mut Bencher) {}上面使用#[bench]做标注,同时函数接受一个参数,b 就是 Rust 提供的评测器。这个写法是固定的。
执行
cargo bench
即可获得结果。
可以看出,rust对测试的支持和go非常相似。
有疑问加站长微信联系(非本文作者)