Rust 测试组织指南:单元测试与集成测试

news2025/2/11 9:38:02

一、为什么要同时使用单元测试与集成测试

  1. 单元测试:更为精细、聚焦某一逻辑单元;可以调用到私有函数,快速定位错误根源。
  2. 集成测试:作为“外部代码”来使用库的公开接口,测试多个模块间的交互,确保整体功能正确。

Rust 的类型系统与所有权机制会在一定程度上减少潜在 Bug,但业务逻辑可能依旧存在错误。将这两种测试结合使用,能有效覆盖从单个函数到库全局的多层面需求,构建更健壮的项目。

二、单元测试(Unit Tests)

1. 放置位置与 #[cfg(test)]

在 Rust 中,单元测试一般放在与被测代码相同的文件中,并位于一个 #[cfg(test)] 模块里。例如,工程中有一个 src/lib.rs 文件,代码可以写成:

// src/lib.rs
pub fn add_two(x: i32) -> i32 {
    x + 2
}

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

    #[test]
    fn it_adds_two() {
        assert_eq!(add_two(2), 4);
    }
}
  • #[cfg(test)]:指定该模块在测试编译时才会被包含,避免在正式构建中编译测试代码。
  • #[test]:标明此函数是一个测试函数,cargo test 会自动执行它。

2. 测试私有函数

与某些语言不同,Rust 并不禁止测试私有函数。原因是测试本质上只是另一个普通模块,可以通过 use super::* 访问父模块中的私有接口。例如:

fn internal_add(a: i32, b: i32) -> i32 {
    a + b
}

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

    #[test]
    fn it_adds_two_numbers() {
        assert_eq!(internal_add(3, 4), 7);
    }
}

如果你遵循“不测试私有函数”的原则,也可只在公开接口上编写测试。Rust 不作强制约束,一切由你和团队的测试理念决定。

三、集成测试(Integration Tests)

1. 测试文件放在 tests 目录

与单元测试不同,集成测试位于项目根目录下的 tests 文件夹,每个文件都会被当作独立的测试 crate。只需创建该目录,即可让 cargo test 自动编译并执行其中所有测试。

目录结构示例:

my_project
├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
└── tests
    └── integration_test.rs

一个简单的集成测试文件可能如下:

// tests/integration_test.rs
use my_project::add_two;

#[test]
fn test_add_two() {
    assert_eq!(add_two(2), 4);
}

要点:

  • 集成测试文件必须显式地 use 库(如 my_project::add_two);
  • 不需要加 #[cfg(test)],因为该目录下文件仅在 cargo test 时被编译;
  • 每个文件为一个独立 crate,彼此之间互不影响。

2. 运行与筛选集成测试

执行 cargo test 时,Rust 将依次运行单元测试集成测试和(若存在)文档测试。如果只想运行某个集成测试文件,可以使用:

cargo test --test integration_test

其中 integration_test 为去掉 .rs 后的文件名(即 integration_test.rs)。

3. 在集成测试间共享辅助代码

有时,多个集成测试文件可能需要调用同样的初始化或辅助逻辑。这些代码可放在 tests/common/mod.rs 中,再在测试文件里 mod common; 引入并使用。例如:

tests
├── common
│   └── mod.rs
└── integration_test.rs
  • common/mod.rs 中定义 pub fn setup() { ... } 等;
  • integration_test.rsmod common; 后,就可在测试内调用 common::setup()

这样不会将 common 视为一个单独的测试文件,也不会在 cargo test 输出中显示 “running 0 tests”。

四、二进制项目的测试建议

如果你主要编写的是二进制(只有 src/main.rs)而没有 src/lib.rs,那么集成测试就很难直接引用 main 函数中的内容。对此通常的推荐做法是:

  1. src/lib.rs 中放置核心逻辑;
  2. src/main.rs 仅做轻量包装和调用;
  3. 集成测试只需要引入 lib.rs 中的公共函数即可测试大部分逻辑。

这样可以保证你的主要业务功能既能被二进制入口 (main.rs) 调用,也能被测试模块引用。

五、结语

Rust 为单元测试和集成测试都提供了一套清晰的机制和约定,有效地帮助你分别聚焦模块内部和整体外部 API 的正确性。通常的建议是:

  1. 单元测试:与实现代码同文件、写入 #[cfg(test)] 模块,用于快速检测单个函数或模块的正确性;可测试私有函数细节。
  2. 集成测试:新建 tests/ 目录,用来模拟用户会如何使用你的库公共 API,确保跨模块协作行为正确。

通过同时使用这两种测试方法,你可以在细节层面和集成层面构建起更完备的测试体系。正如业界常言:没有测试的代码只能算是一次大胆的尝试。借助 Rust 强大的类型系统及其便利的测试组织方式,相信你能更轻松地写出安全、可靠的高质量程序!

祝你玩转 Rust 测试!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day62_补20250210_图论part6_108冗余连接|109.冗余连接II

Day62_20250210_图论part6_108冗余连接|109.冗余连接II 108冗余连接 【把题意转化为并查集问题】 题目 有一个图,它是一棵树,他是拥有 n 个节点(节点编号1到n)和 n - 1 条边的连通无环无向图(其实就是一个线形图&am…

kafka消费端之消费者协调器和组协调器

文章目录 概述回顾历史老版本获取消费者变更老版本存在的问题 消费者协调器和组协调器新版如何解决老版本问题再均衡过程**第一阶段CFIND COORDINATOR****第二阶段(JOINGROUP)**选举消费组的lcader选举分区分配策略 第三阶段(SYNC GROUP&…

IDEA升级出现问题Failed to prepare an update Temp directory inside installation

IDEA升级出现问题"Failed to prepare an update Temp directory inside installation…" 问题来源: 之前修改了IDEA的默认配置文件路径,然后升级新版本时就无法升级,提示"Failed to prepare an update Temp directory insid…

十款开源的论坛建站工具

以下是十款开源的论坛建站工具,它们各具特色,能够满足不同用户的需求: Discuz!(Crossday Discuz! Board) 特点:基础架构采用web编程组合PHPMySQL,用户可以在不需要任何编程的基础上,…

vue学习6

1. 智慧商城 1. 路由设计配置 单个页面&#xff0c;独立展示的&#xff0c;是一级路由 2.二级路由配置 规则&组件配置导航链接配置路由出口 <template><div id"app"><!--二级路由出口--><router-view></router-view><van-…

线程池以及日志、线程总结

一、线程池以及日志 1、基础线程池写法 主线程在main函数中构建一个线程池&#xff0c;初始化(Init)后开始工作(Start) 此时线程池中每个线程都已经工作起来了&#xff0c;只是任务队列中任务为空&#xff0c;所有线程处于休眠状态(通过线程同步中的条件变量实现&#xff0c…

Vue 响应式渲染 - 过滤应用

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue响应式渲染综合 - 过滤应用 目录 过滤应用 引入vue Vue设置 设置页面元素 模糊查询过滤实现 函数表达式实现 总结 过滤应用 综合响应式渲染做一个输入框&#xff0c;用来实现&#xff1b;搜索输入框关键词符合列表。…

【ThreeJS Basics 1-3】Hello ThreeJS,实现第一个场景

文章目录 环境创建一个项目安装依赖基础 Web 页面概念解释编写代码运行项目 环境 我的环境是 node version 22 创建一个项目 首先&#xff0c;新建一个空的文件夹&#xff0c;然后 npm init -y , 此时会快速生成好默认的 package.json 安装依赖 在新建的项目下用 npm 安装依…

深入理解动态代理

为什么需要动态代理 对于代码的增强逻辑我们是清楚具体实现的,一种方式是增强逻辑作为委托类,被其他业务类调用, 这样会有很多重复代码,而且,当需要根据动态参数来决定增强逻辑时,重复代码会更多,逻辑会更不清晰 二,也是动态代理产生的原始需求,解决类爆照问题, 所以…

Cherry Studio之DeepSeek联网/本地,建属于自己的AI助理!

上一篇文章&#xff0c;讲了DeepSeek-R1部署到本地的方法。这一篇文章&#xff0c;我们让DeepSeek再一次升级&#xff0c;通过图形化界面来交互&#xff0c;从而变成我们的AI助理&#xff0c;让DeepSeek R1发挥最大实力&#xff01; 首选需要借助硅基流动的API接口&#xff0c…

IGBT的两级关断

IGBT&#xff08;绝缘栅双极型晶体管&#xff09;的两级关断&#xff08;Two-stage turn-off&#xff09;是一种优化关断过程的方法&#xff0c;主要用于减少关断时的电压过冲和dv/dt&#xff08;电压变化率&#xff09;过高的问题&#xff0c;特别是在大功率应用中&#xff08…

【STM32】ADC

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信号…

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 0基础…

Chapter3:结构化程序设计

参考书籍&#xff1a;《C#边做边学》&#xff1b; 3.结构化程序设计 3.1 结构化程序设计的3种基本结构 顺序结构&#xff1a;先执行 A {\rm A} A语句&#xff0c;再执行 B {\rm B} B语句&#xff0c;两者是顺序执行的关系&#xff1b; 选择结构&#xff1a;根据所定选择条件为…

白话文实战Nacos(保姆级教程)

前言 上一篇博客 我们创建好了微服务项目,本篇博客来体验一下Nacos作为注册中心和配置中心的功能。 注册中心 如果我们启动了一个Nacos注册中心,那么微服务比如订单服务,启动后就可以连上注册中心把自己注册上去,这过程就是服务注册。每个微服务,比如商品服务都应该注册…

智能理解 PPT 内容,快速生成讲解视频

当我们想根据一版 PPT 制作出相对应的解锁视频时&#xff0c;从撰写解锁词&#xff0c;录制音频到剪辑视频&#xff0c;每一个环节都需要投入大量的时间和精力&#xff0c;本方案将依托于阿里云函数计算 FC 和百炼模型服务&#xff0c;实现从 PPT 到视频的全自动转换&#xff0…

IEC61850标准下的数据和数据模型服务的详细介绍

目录 一、摘要 二、概述 三、详细介绍 1、读服务器目录(GetServerDirectory) 2、读逻辑设备目录(GetLogicalDeviceDirectory) 3、读逻辑节点目录(GetLogicalNodeDirectory) 4、读全部数据值(GetAllDataValues) 5、读数据值(GetDataValues) 6、设置数据值(SetDataValues…

R语言LCMM多维度潜在类别模型流行病学研究:LCA、MM方法分析纵向数据

全文代码数据&#xff1a;https://tecdat.cn/?p39710 在数据分析领域&#xff0c;当我们面对一组数据时&#xff0c;通常会有已知的分组情况&#xff0c;比如不同的治疗组、性别组或种族组等&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 然而&#xff0c;…

5. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--Nacos

一、什么是Nacos Nacos 是阿里巴巴开源的一款云原生应用基础设施&#xff0c;它旨在简化微服务架构中服务治理和配置管理的复杂性。通过 Nacos&#xff0c;服务在启动时可以自动注册&#xff0c;而其他服务则可以通过名称来查找并访问这些注册好的实例。同时&#xff0c;Nacos…

VUE项目中实现权限控制,菜单权限,按钮权限,接口权限,路由权限,操作权限,数据权限实现

VUE项目中实现权限控制&#xff0c;菜单权限&#xff0c;按钮权限&#xff0c;接口权限&#xff0c;路由权限&#xff0c;操作权限&#xff0c;数据权限实现 权限系统分类&#xff08;RBAC&#xff09;引言菜单权限按钮权限接口权限路由权限 菜单权限方案方案一&#xff1a;菜单…