【Rust自学】11.10. 集成测试

ops/2025/1/15 7:04:38/

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
请添加图片描述

11.10.1. 什么是集成测试

在Rust里,集成测试完全位于被测试库的外部。集成测试调用库的方式和其他代码一样,这也意味着集成测试只能调用对外公开的API。

集成测试的目的是验证被测试库的多个部分能否正确地一起工作,这一点有别于单元测试单元测试比较小也比较专注,每次只对一个模块进行隔离的测试,还可以测试私有的(private)接口。

有时候能够独立运行的一些单元代码在合在一起运用时也会发生问题,集成测试正是为了今早发现和解决这种问题存在的。所以说,集成测试的覆盖率很重要

11.10.2. tests目录

创建集成测试需要先创建tests目录。

这个目录是与src目录并列,cargo会自动在这个目录下寻找集成测试文件。在这个目录下可以创建任意多的集成测试文件,cargo会在编译时把每个测试文件都处理为一个单独的包,也就是一个单独的crate

下面来演示一下创建集成测试文件:

1. 创建tests目录

在与src同级的目录下创建名为tests的文件夹:
请添加图片描述

2. 创建测试文件

tests目录下创建.rs的测试文件,给它取个名字,这里我起的是integration_test.rs
请添加图片描述

3. 把测试代码移到测试文件里

以上一篇文章的代码为例(lib.rs):

rust">pub fn add_two(a: usize) -> usize {internal_adder(a, 2)
}fn internal_adder(left: usize, right: usize) -> usize {left + right
}#[cfg(test)]
mod tests {use super::*;#[test]fn internal() {let result = internal_adder(2, 2);assert_eq!(result, 4);}
}

由于每一个集成测试文件都是一个单独的crate,所以这个文件(integration_test.rs)想要测试lib.rs这个crate的内容就得先导入作用域。

在这个例子中,由于我给这个项目命名为RustStudy,所以这个package(包)的名字就是RustStudy,如果你不清楚可以到你的cargo.toml里看name这个参数。在这个例子中,导入作用域写:use RustStudy;即可,如果你想指定到具体的函数也行。

导入完后直接写测试函数就可以,不需要写#[cfg(test)],因为tests目录下的代码只会在运行cargo test的时候被执行,只需要给测试函数标注#[test]即可。

整体代码如下(integration_test.rs):

rust">use RustStudy;#[test]
fn it_adds_two() {let result = RustStudy::add_two(2);assert_eq!(result, 4);
}

输出:

$ cargo testCompiling adder v0.1.0 (file:///projects/adder)Finished `test` profile [unoptimized + debuginfo] target(s) in 1.31sRunning unittests src/lib.rs (target/debug/deps/adder-1082c4b063a8fbe6)running 1 test
test tests::internal ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sRunning tests/integration_test.rs (target/debug/deps/integration_test-1082c4b063a8fbe6)running 1 test
test it_adds_two ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sDoc-tests adderrunning 0 teststest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

可以看到,这个输出显示运行了两个测试,这是因为一个是来自lib.rs的测试(单元测试),一个是来自integration_test.rs的测试(集成测试)。

11.10.3. 运行指定的集成测试

运行一个特定的集成函数,可以使用cargo test 指定的函数名;运行某个测试文件内的所有测试函数,可以使用cargo test --test 文件名

看个例子:
请添加图片描述

现在tests下有两个文件,如果我只希望运行integration_test.rs里的测试函数,那么就输入指令:

cargo test --test integration_test

11.10.4. 集成测试中的子模块

由于tests目录下的每个文件被编译成单独的crate,所以这些文件互不共享行为(与src目录下的文件规则不同)。

那如果我想将测试函数中重复出现的逻辑提取到一个helper函数中,避免代码重复,该怎么写呢?

举个例子,我在tests目录下写了common.rs这个文件用于存储helper函数:
请添加图片描述

试试执行测试:

$ cargo testCompiling adder v0.1.0 (file:///projects/adder)Finished `test` profile [unoptimized + debuginfo] target(s) in 0.89sRunning unittests src/lib.rs (target/debug/deps/adder-92948b65e88960b4)running 1 test
test tests::internal ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sRunning tests/common.rs (target/debug/deps/common-92948b65e88960b4)running 0 teststest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sRunning tests/integration_test.rs (target/debug/deps/integration_test-92948b65e88960b4)running 1 test
test it_adds_two ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sDoc-tests adderrunning 0 teststest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

可以看到,在测试结果中出现了对common.rs的测试。但因为common.rs是用来存储helper函数的,所以它本身不需要也没必要被测试,这种写法是错误的。

正确的做法是在tests目录下创建一个common目录,在里面创建mod.rs,把helper函数都放到这里面来,把原来的common.rs删掉即可:
请添加图片描述

这实际上是另外一种可以被Rust理解的命名规范,Rust不会把common模块视作为集成测试文件,而在测试输出中也不会出现common了,因为tests下的子目录不会被视为单独的crate进行编译。

如果要在集成测试文件中使用这里面的内容,只需要在文件开头写mod 文件夹名;即可,在这个例子中就是mod common;。使用时写common::你想要的函数,在这个例子中就是common::setup()

11.10.5. 针对binary crate的集成测试

如果项目是二进制包(binary crate),也就是只含有src/main.rs没有src/lib.rs,就不可以在tests目录下创建集成测试,即使有,也无法把main.rs的函数导入作用域。因为只有library crate(也就是有lib.rs)才能暴露函数给其它crate用。

binary crate意味着独立运行。因此,Rust的binary项目通常会把这些逻辑都放在lib.rs里,而在main.rs里只有简单的调用。这样做项目就会被视为library crate,就可以使用集成测试来检查代码。


http://www.ppmy.cn/ops/150226.html

相关文章

实用好软-----电脑端链接手机 免root权限管理手机 调试安卓

来自知名开发者开发。而且近期更新了全功能的搞机工具。对于链接电脑进行管理手机比较方便。新版重写了多线程逻辑,修复大量卡顿与无响应问题,同时优化了设备检测逻辑,启动更快更丝滑。还有大量新增免ROOT功能。对于玩机来说非常不错 由于AD…

《计算机网络》课后探研题书面报告_了解PPPoE协议

PPPoE协议的工作原理与应用分析 摘 要 PPPoE(Point-to-Point Protocol over Ethernet)是一种广泛应用于宽带接入的网络协议,特别是在DSL(数字用户线路)和光纤网络中具有重要的应用价值。PPPoE结合了PPP协议的认证、加…

Jenkins质量门禁设计方案的深入探讨

Jenkins作为一个开源的自动化服务器,它通过简化持续集成和持续交付流程,使得软件测试变得更加高效。质量门禁设计方案结合了Jenkins的以下几项核心功能: 持续集成(CI) :通过自动化构建和测试,提…

【STM32-学习笔记-4-】PWM、输入捕获(PWMI)

文章目录 1、PWMPWM配置 2、输入捕获配置3、编码器 1、PWM PWM配置 配置时基单元配置输出比较单元配置输出PWM波的端口 #include "stm32f10x.h" // Device headervoid PWM_Init(void) { //**配置输出PWM波的端口**********************************…

青少年编程与数学 02-006 前端开发框架VUE 23课题、UI框架

青少年编程与数学 02-006 前端开发框架VUE 23课题、UI框架 一、UI框架二、Element Plus三、Element Plus如何应用1. 安装Element Plus2. 配置Vite或Webpack对于Vite项目:对于Webpack项目: 3. 在main.js中全局导入Element Plus4. 在组件中使用Element Plu…

Outlook 无网络连接[2604] 错误解决办法

Outlook 是微软公司开发的一款广泛使用的电子邮件客户端,广泛应用于个人用户和企业办公环境中。然而,许多用户在使用 Outlook 时可能会遇到“无网络连接”或者“错误代码 [2604]”等问题。这个错误通常会导致 Outlook 无法正常连接到邮件服务器&#xff…

21天学通C++第八章——指针

C虽然可以动态的管理内存,但是并不能像其他高级语言如JAVA、C#有自动垃圾收集器去对应用程序的内存进行清理。 常见指针错误 内存泄漏 解释: 在使用完new申请内存之后,没有配套的delete,则之后会产生内存泄漏。 即如何理解&a…

登录、注册、忘记密码、首页HTML模板

<!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>登录</title><style>body {display: fl…