当前位置: 首页 > news >正文

【Rust自学】11.4. 用should_panic检查恐慌

11.4 用should_panic检查恐慌

11.4.1. 验证错误处理的情况

除了验证代码是否返回正确的值,测试还需要验证代码是否如预期处理了错误情况。例如,可以编写一个测试来验证代码是否在特定条件下发生恐慌。

这类测试需要额外的should_panic属性。用它标记的函数,如果函数内发生了恐慌,测试就通过;否则就失败。

看个例子:

pub struct Guess { value: i32, } impl Guess { pub fn new(value: i32) -> Guess { if value < 1 || value > 100 { panic!("Guess value must be between 1 and 100, got {value}."); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic] fn greater_than_100() { Guess::new(200); } }
  • 结构体Guess有一个类型为i32的字段value。它提供关联函数new用于创建Guess实例,但前提是传给new的参数在1到100之间;否则就会恐慌。
  • greater_than_100测试函数给new传入大于100的值。这时应该发生恐慌,所以给这个测试函数加了should_panic属性,也就是写#[should_panic]

测试结果:

$ cargo test Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished `test` profile [unoptimized + debuginfo] target(s) in 0.12s Running unittests src/lib.rs (target/debug/deps/guessing_game-bdc6b9a45c563cc0) running 1 test test tests::greater_than_100 - should panic ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests guessing_game running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

现在故意引入一个bug,把new里的value > 100检查去掉:

pub struct Guess { value: i32, } impl Guess { pub fn new(value: i32) -> Guess { if value < 1 { panic!("Guess value must be between 1 and 100, got {value}."); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic] fn greater_than_100() { Guess::new(200); } }

这时测试函数中的Guess::new(200);不会恐慌。但因为函数加了should_panic标记,本应恐慌却没有恐慌的测试就会失败:

$ cargo test Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished `test` profile [unoptimized + debuginfo] target(s) in 0.09s Running unittests src/lib.rs (target/debug/deps/guessing_game-bdc6b9a45c563cc0) running 1 test test tests::greater_than_100 - should panic ... FAILED failures: ---- tests::greater_than_100 stdout ---- note: test did not panic as expected at src/lib.rs:21:8 failures: tests::greater_than_100 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`

11.4.2. 让should_panic更精确

有时使用should_panic的测试会有点含糊,因为它们只能说明代码是否发生了恐慌,即使这个恐慌并不是程序员预期的那个。

为了让测试更精确,可以为should_panic添加一个可选的expected参数。这样程序就会检查失败消息中是否包含指定的文字。

看个例子:

pub struct Guess { value: i32, } impl Guess { pub fn new(value: i32) -> Guess { if value < 1 { panic!( "Guess value must be greater than or equal to 1, got {value}." ); } else if value > 100 { panic!( "Guess value must be less than or equal to 100, got {value}." ); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "less than or equal to 100")] fn greater_than_100() { Guess::new(200); } }
  • 上面的结构体稍作了修改:newvalue < 1value > 100的情况现在使用两条不同的恐慌信息。
  • should_panic添加了expected参数,=后面的文字就是期待的错误信息。只有函数发生了恐慌,并且恐慌信息包含期待的文字,测试才通过;否则就失败。

这个程序肯定能通过。

用同样的套路手动引入错误。例如,把new里小于1和大于100时的恐慌信息交换一下:

pub struct Guess { value: i32, } impl Guess { pub fn new(value: i32) -> Guess { if value < 1 { panic!( "Guess value must be less than or equal to 100, got {value}." ); } else if value > 100 { panic!( "Guess value must be greater than or equal to 1, got {value}." ); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "less than or equal to 100")] fn greater_than_100() { Guess::new(200); } }

测试结果:

$ cargo test Compiling guessing_game v0.1.0 (file:///projects/guessing_game) Finished `test` profile [unoptimized + debuginfo] target(s) in 0.08s Running unittests src/lib.rs (target/debug/deps/guessing_game-bdc6b9a45c563cc0) running 1 test test tests::greater_than_100 - should panic ... FAILED failures: ---- tests::greater_than_100 stdout ---- thread 'tests::greater_than_100' (457156) panicked at src/lib.rs:12:13: Guess value must be greater than or equal to 1, got 200. note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: panic did not contain expected string panic message: "Guess value must be greater than or equal to 1, got 200." expected substring: "less than or equal to 100" failures: tests::greater_than_100 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`

失败信息表明测试确实发生了恐慌,但恐慌消息没有包含期待的字符串less than or equal to 100。在这种情况下,我们实际收到的恐慌信息是Guess value must be greater than or equal to 1, got 200.。根据这些信息就足以修复这个bug。

http://www.jsqmd.com/news/1249468/

相关文章:

  • 联邦学习通信效率优化:模型压缩与异步协议实践
  • VS Code 远程部署 claude code 插件
  • 杭州 2026 旧腕表回收避坑,正规门店交易细节拆解 - 每日生活报
  • 基于ddddocr与Hu矩的验证码识别技术实践
  • 2026年联想代理商怎么找:联想授权代理商选择推荐指南 - 全域品牌推荐
  • 收藏!10个企业级AI高频应用场景,小白也能轻松落地实践
  • 嵌入式ADC寄存器深度解析:中断、FIFO与通道选择实战指南
  • 深入解析MibSPI高级功能:灵活片选与并行传输实战指南
  • 武汉刻章的流程是什么看完这篇秒懂 - 跑政通
  • 联系方式:133 9303 2100|2026石家庄市区及周边县城香奈儿包包回收,毓典寄卖行十年老店可上门回收 - 小何收的顶
  • 【Rust自学】11.3. 自定义错误信息
  • 2026肠胃弱猫咪羊奶粉深度横评:5项指标实测+5款主流产品对比,玻璃胃养猫避坑指南
  • ChatGPT、Codex 与 Legacy Code:AI 是老系统的救星,还是压垮它的最后一根稻草?(Plus/Pro 实战观察)
  • DMA裸板驱动使用说明
  • 【Rust自学】6.4. 简单的控制流-if let
  • 小米路由器刷入Breed与OpenWrt详细流程并实现远程管理本地软路由
  • 济南上门回收手表靠谱吗?上门交易风险盘点 - 好物测评局
  • 2026淮南煤矿/电厂职工注意!国开大专采矿/电气自动化专业,助力职称评定! - 我叫小周
  • ARM架构下安装新版docker及docker-compose
  • 2026内蒙古中考落榜别灰心!电大中专保留学籍,曲线救国圆你大学梦! - 我叫小周
  • 宁波实体黄金回收店|大盘价当场结算 - 大牌深度测评
  • 2026高钙猫咪羊奶粉品牌实测横评:5维度实测,附避坑指南+选型方案
  • 大模型推理加速技术:ATB架构与优化实践
  • Nginx 负载均衡和反向代理
  • 深入解析MCU的IOMM:寄存器映射、引脚复用与错误处理实战
  • 2026 欧米茄海马闲置在家贬值?青岛合扬全城实体网点,评估完毕即刻回款! - 好物测评局
  • 每天节省2.7小时!AI自动发邮件的12种高价值场景(销售跟进、客户回访、内部通知全覆盖)
  • 2026年全国混凝土色差修复新标准:3步实现永久无痕
  • Django毕设选题推荐:基于 Django社区防疫数据监测与信息公示系统设计 面向社区的疫情人员信息登记管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 2026年武汉东湖光电职业技术学校报考指南 - 湖北找学校