【Rust自学】11.2. 断言(Assert)
11.2 断言(Assert)11.2.1. 使用assert!宏检查测试结果assert!宏来自标准库用于判断某个条件是否为true。它接收一个返回类型为布尔值的表达式- 当assert!内的值为true时测试通过assert!也不会做多余的操作。- 当assert!内的值为false时assert!会调用panic!测试失败。看个例子#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn can_hold(self, other: Rectangle) - bool { self.width other.width self.height other.height } }结构体Rectangle存储矩形的宽和高。它定义了can_hold方法用于判断一个矩形能否容纳另一个矩形不考虑斜着放。逻辑很好理解只要看当前矩形的宽和高是否都大于另一个矩形即可。该如何测试这个方法呢因为它的返回类型正好是bool所以用assert!再合适不过#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn can_hold(self, other: Rectangle) - bool { self.width other.width self.height other.height } } #[cfg(test)] mod tests { use super::*; #[test] fn larger_can_hold_smaller() { let larger Rectangle { width: 8, height: 7, }; let smaller Rectangle { width: 5, height: 1, }; assert!(larger.can_hold(smaller)); } }由于test是一个模块所以test模块内如果想使用外部的内容就必须先导入到当前作用域。这里写的是use super::*;*会把外部模块的所有内容导入进test模块。有关这部分的详细内容可以看 7.2. 路径PathPt.1 和 7.3. 路径PathPt.2。然后看下面的测试函数。首先声明了两个矩形larger和smaller分别存储大矩形和小矩形的宽高这就是准备(Arrange)阶段。下面的assert!宏调用了can_hold这就是运行(Act)阶段。最后用assert!来判断测试是否成功。在这个例子中larger存储的宽高绝对可以容纳smaller所以结果一定是true测试通过。运行cargo test$ cargo test Compiling rectangle v0.1.0 (file:///projects/rectangle) Finished test profile [unoptimized debuginfo] target(s) in 0.12s Running unittests src/lib.rs (target/debug/deps/rectangle-2f89d610a9fe6c00) running 1 test test tests::larger_can_hold_smaller ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests rectangle running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s那如果小矩形容纳不了大矩形呢#[cfg(test)] mod tests { use super::*; #[test] fn larger_can_hold_smaller() { //... } #[test] fn smaller_cannot_hold_larger() { let larger Rectangle { width: 8, height: 7, }; let smaller Rectangle { width: 5, height: 1, }; assert!(!smaller.can_hold(larger)); } }又声明了另一个测试函数smaller_cannot_hold_larger。smaller.can_hold(larger)一定返回false但前面加了取反运算符!所以最终assert!收到的仍然是true测试通过$ cargo test Compiling rectangle v0.1.0 (file:///projects/rectangle) Finished test profile [unoptimized debuginfo] target(s) in 0.08s Running unittests src/lib.rs (target/debug/deps/rectangle-2f89d610a9fe6c00) running 2 tests test tests::larger_can_hold_smaller ... ok test tests::smaller_cannot_hold_larger ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests rectangle running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s两个测试都能通过说明can_hold方法大概没问题。现在改一下这个方法把can_hold中的宽度比较从改成#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn can_hold(self, other: Rectangle) - bool { self.width other.width self.height other.height } }逻辑现在就错了。再运行同样的测试函数$ cargo test Compiling rectangle v0.1.0 (file:///projects/rectangle) Finished test profile [unoptimized debuginfo] target(s) in 0.07s Running unittests src/lib.rs (target/debug/deps/rectangle-2f89d610a9fe6c00) running 2 tests test tests::smaller_cannot_hold_larger ... ok test tests::larger_can_hold_smaller ... FAILED failures: ---- tests::larger_can_hold_smaller stdout ---- thread tests::larger_can_hold_smaller (454276) panicked at src/lib.rs:28:9: assertion failed: larger.can_hold(smaller) note: run with RUST_BACKTRACE1 environment variable to display a backtrace failures: tests::larger_can_hold_smaller test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass --lib有一个测试失败了说明错误被成功捕获了。这也是编写测试的目的尽早发现问题。11.2.2. 使用assert_eq!和assert_ne!测试相等性assert_eq!中的eq指的是equal相等assert_ne!中的ne指的是not equal不相等。这两者都来自标准库。这两个宏接收两个参数并判断这两个值是否相等。通常把被测试代码的结果作为一个参数把期待的结果作为另一个参数然后宏就会检查这两个结果是否相等。实际上这两个宏的用法很像和!运算符。不同之处在于如果失败它们会自动打印出两个参数的值从而帮助开发者理解测试失败的原因。使用这两个宏有一定要求。它们用debug格式打印值所以参数必须实现PartialEq和Debug这两个trait。所有基本类型和大部分标准库类型都已经实现了但自定义结构体和枚举必须自行实现这些trait。这两个trait都是可派生的所以对自定义类型通常只要这样写即可#[derive(PartialEq, Debug)] struct Point { x: i32, y: i32, }加上这个标注后就可以用assert_eq!/assert_ne!比较Point值并且断言失败时能够打印出这些值。下面是一个使用assert_eq!的例子pub fn add_two(a: usize) - usize { a 2 } #[cfg(test)] mod tests { use super::*; #[test] fn it_adds_two() { let result add_two(2); assert_eq!(result, 4); } }add_two函数会给参数加2。测试函数it_adds_two调用了add_two因为2 2 4所以期待的add_two(2)的值是4把4和函数调用放进宏里即可。其实在Rust中期待的值和函数调用的位置是可以互换的。有些语言对顺序有明确要求但Rust没有。放在左边第一个参数的值只是叫做左值另一个叫做右值。输出$ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test profile [unoptimized debuginfo] target(s) in 0.07s Running unittests src/lib.rs (target/debug/deps/adder-302521ba8d0f0bdf) running 1 test test tests::it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s接下来引入一个逻辑错误把add_two的a 2改成a 3其余不变看看会发生什么pub fn add_two(a: usize) - usize { a 3 } #[cfg(test)] mod tests { use super::*; #[test] fn it_adds_two() { let result add_two(2); assert_eq!(result, 4); } }输出$ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished test profile [unoptimized debuginfo] target(s) in 0.07s Running unittests src/lib.rs (target/debug/deps/adder-302521ba8d0f0bdf) running 1 test test tests::it_adds_two ... FAILED failures: ---- tests::it_adds_two stdout ---- thread tests::it_adds_two (455023) panicked at src/lib.rs:12:9: assertion left right failed left: 5 right: 4 note: run with RUST_BACKTRACE1 environment variable to display a backtrace failures: tests::it_adds_two test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass --lib测试抓住了这个bug。失败信息显示left是5也就是add_two(2)的结果right是4。另外还有assert_ne!两个值不相等时通过相等时失败。它最适合用在你不确定具体会得到什么值、但知道它绝对不该是某个值的场合。

相关新闻

RNN训练中的梯度问题与梯度裁剪实战解析

RNN训练中的梯度问题与梯度裁剪实战解析

1. RNN训练的核心挑战解析循环神经网络(RNN)作为处理序列数据的经典模型,其训练过程远比前馈神经网络复杂。我在实际项目中使用RNN处理自然语言和时间序列数据时,最常遇到的三个"拦路虎"就是:梯度消失&#…

2026/7/23 18:52:42 阅读更多 →
OpenClaw提示词工程:AI高效交互的核心技术解析

OpenClaw提示词工程:AI高效交互的核心技术解析

1. OpenClaw提示词工程解析OpenClaw作为当前AI领域的热门工具,其核心提示词的质量直接决定了输出结果的专业性和可用性。这套完整中文版提示词库经过大量实际项目验证,包含超过200个经过优化的标准提示模板,覆盖技术咨询、内容创作、数据分析…

2026/7/23 18:52:42 阅读更多 →
AI Agent时代程序员的三大核心竞争力和转型指南

AI Agent时代程序员的三大核心竞争力和转型指南

1. 为什么AI Agent不会让你失业,但不懂的程序员可能会?最近总有人问我:"AI Agent会不会抢走我们的饭碗?"作为一个从传统软件开发转型到大模型应用的开发者,我想说:工具从来不会淘汰人&#xff0c…

2026/7/23 18:52:42 阅读更多 →

最新新闻

问题:如何监控生产时效,提升效率?

问题:如何监控生产时效,提升效率?

引言:计划表≠生产效率 在工厂的日常运营中,生产计划表(或称排程表)是生产的“指挥棒”。然而,许多管理者常常陷入一个误区:认为只要计划表做得漂亮、排得满,生产效率就自然上去了。他们每天盯着…

2026/7/23 19:08:48 阅读更多 →
【Springboot毕设全套源码+文档】基于springboot电脑商城系统的设计与实现(丰富项目+远程调试+讲解+定制)

【Springboot毕设全套源码+文档】基于springboot电脑商城系统的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/23 19:08:48 阅读更多 →
Agentic自主进化机制:合成数据与强化学习的实践

Agentic自主进化机制:合成数据与强化学习的实践

1. 项目概述:Agentic自主进化机制的核心逻辑去年在开发一个对话系统时,我遇到了典型的数据瓶颈——人工标注成本高、覆盖场景有限。当时尝试用强化学习(RL)做在线学习,但探索效率太低。直到看到Agentic自主进化这个概念…

2026/7/23 19:08:48 阅读更多 →
区域功能节点的工程角色:国家数据基础设施的跨域路由层怎么理解

区域功能节点的工程角色:国家数据基础设施的跨域路由层怎么理解

“区域功能节点—业务节点—接入连接器”正在成为国家数据基础设施的通用架构语言。这套分层最早在跨省数据流通的生产实践中成型,本文从工程视角拆解每层的职责边界与设计要点。三层各管什么。接入连接器是终端接入层:负责数据源接入、规则执行与使用控…

2026/7/23 19:08:48 阅读更多 →
限时开放|AI自动发邮件SOP模板库(含27个行业话术+13类触发条件+5套A/B测试方案),仅剩最后83份授权码

限时开放|AI自动发邮件SOP模板库(含27个行业话术+13类触发条件+5套A/B测试方案),仅剩最后83份授权码

更多请点击: https://codechina.net 第一章:AI自动发邮件教程 AI驱动的邮件自动化正成为提升工作效率的关键实践。本章聚焦于使用Python结合主流AI与邮件服务API,构建可定制、可扩展的自动发信系统。核心依赖包括 openai(用于生成…

2026/7/23 19:08:48 阅读更多 →
Windows安装Ubuntu20.04系统(双系统)

Windows安装Ubuntu20.04系统(双系统)

安装准备:一个空白U盘(≥4G),电脑足够的空闲硬盘空间(用来安装Ubuntu系统) 1.Ubuntu镜像文件 历史版本选择“其他下载”——“查看历史版本”——“找到所需版本(个人下载选择桌面映像&#x…

2026/7/23 19:07:48 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻