vlambda博客
学习文章列表

Rust能力养成之(15)集成测试



前言



上一篇我们讲了单元测试,这篇进入集成测试的内容

单元测试可以检测和实验crate和单个模块的私有接口,相比之下,集成测试就有点像黑盒测试,目的是从消费者的角度来测试crate公共接口从端到端(end-to-end)的使用情况。在代码方面,编写集成测试和单元测试之间并没有太大的区别,唯一的区别在于目录结构和项目需要被公开(public)


第一个集成测试



如前所述,Rust期待甚至是要求所有集成测试都位于tests/目录中。在测试所需使用的库时,test /目录中的各个文件被编译为单独的二进制crate。在下面的示例中,我们将通过运行cargo new integration_test--lib创建一个新的crate,以及一个与前面的单元测试中的相同函数sum,但现在我们添加了test /目录,定义一个集成测试函数,如下:
// integration_test/tests/sum.rs
use integration_test::sum;
#[test]fn sum_test() { assert_eq!(sum(6, 8), 14); }

从上面代码可见,首先引入函数和的作用域。其次,我们有一个函数sum_test,调用sum并对返回值进行断言。当尝试运行cargo test时,会出现以下错误:

Rust能力养成之(15)集成测试

这个错误似乎是合理:我们希望crate的用户使用sum函数,但是在crate中,默认情况下定义为一个私有函数

Rust能力养成之(15)集成测试

因此,在sum函数之前添加了pub修改器并运行cargo测试后,测试可以通过:

Rust能力养成之(15)集成测试

下面是integration_test这个crate的目录视图:
. ├── Cargo.lock├── Cargo.toml├── src│ └── lib.rs└── tests └── sum.rs

作为一个集成测试的例子,这是非常简单的,但要点是,当我们编写集成测试时,使用被测试的crate,就像一个新用户在使用这个库一样,可见用户体验在集成测试中也是很重要的。


共享代码(Sharing common code)



就像集成测试经常出现的情况一样,在实际运行测试之前,我们可能需要放置一些设置(setup)拆分相关(teardown-related)的代码,通常这些代码会被test /目录中的所有文件共享。如果需要共享代码,可以通过创建模块作为共享公共代码的目录,或者使用模块foo.rs,并在我们的integration 测试文件中通过添加mod关键字来声明对相关共享代码的依赖。这里我们举个例子,先在之前用过的test /目录中,添加了一个common.rs模块,其中有两个函数---setup和teardown:
// integration_test/tests/common.rs
pub fn setup() { println!("Setting up fixtures");}
pub fn teardown() { println!("Tearing down");}

在这两个函数中,我们都可以使用 任何类型的与功能装置相关(fixture-related)的代码 。比如你有一个依赖于文本文件存在的集成测试。在我们的函数setup中,可以创建文本文件,而在函数teardown中,我们可以通过删除文件来清理资源。

在test /sum.rs中的集成测试代码中使用这些函数,我们在mod中如此声明:
// integration_test/tests/sum.rs
use integration_test::sum;
mod common;
use common::{setup, teardown};
#[test]fn sum_test() { assert_eq!(sum(6, 8), 14); }
#[test]fn test_with_fixture() { setup(); assert_eq!(sum(7, 14), 21); teardown();}

可以看到,我们添加了另一个函数test_with_fixture,包含对setup和teardown的调用。我们可以使用cargo test_with_fixture来运行这个测试。


正如上图的输出中所能注意到的,我们没有看到println!在setup或teardown函数内的任何地方调用。这是因为,默认情况下,测试工具隐藏或捕获测试函数中的print语句而不发,以使测试结果更整洁,并且只显示测试工具的输出。如果我们想在测试中查看打印语句,我们可以使用cargo test test_with_fixture -- --nocapture运行测试,会有以下输出


现在可以看到打印语句了。我们看下在cargo testtest_with_fixture -- --nocapture中的--标记,之所以需要,是因为我们实际上想要将--nocapture标志传递给测试运行器。--标记代表cargo本身以及之后参数的结束。


后记



以上就是关于集成测试的内容。在本章的最后,我们将创建一个项目,在这个项目中,读者将看到单元测试和集成测试的协同工作。接下来,我们将学习为Rust代码编写文档,这是软件开发中一个容易被忽视但非常重要的部分。



主要参考和建议读者进一步阅读的文献
https://doc.rust-lang.org/book
1.Rust编程之道,2019, 张汉东
2.The Complete Rust Programming Reference Guide,2019, Rahul Sharma,Vesa Kaihlavirta,Claus Matzinger
3.Hands-On Data Structures and Algorithms with Rust,2018,Claus Matzinger
4.Beginning Rust ,2018,Carlo Milanesi
5.Rust Cookbook,2017,Vigneshwer Dhinakaran


01

02

03

04

05

06

07

08

09

10

11

12

13

14