de-vri-es/assert2-rs
GitHub: de-vri-es/assert2-rs
这是一个 Rust 宏库,用于提供增强的断言和检查功能,改善测试代码的可读性和调试体验。
Stars: 130 | Forks: 10
# t's part of a phrase, but here it's a single word.
通用型 [`assert!(...)`](macro.assert.html) 和 [`check!(...)`](macro.check.html) 宏,灵感源自 [Catch2](https://github.com/catchorg/Catch2)。
此外还有一个 [`debug_assert!(...)`](macro.debug_assert.html) 宏,该宏在优化构建模式下默认禁用。
## 为何选择这些宏?
相较于标准库的断言,这些宏具有以下优势:
* 在断言内部使用比较运算符,无需依赖专用宏:`assert!(1 + 1 == 2)`。
* 测试模式匹配:`assert!(let Err(e) = File::open("/non/existing/file"))`。
* 使用 [let 链](https://blog.rust-lang.org/2025/06/26/Rust-1.88.0/#let-chains)(即便在 Rust 1.88 之前的编译器版本中也可用)。
* 清晰展示 `&&` 链中哪部分失败。
* 可在后续代码中通过 `assert!(...)` 复用模式匹配捕获的变量。
* 使用 `check!(...)` 可在发生 panic 前执行多项检查。
* 彩色失败消息!
* 高亮显示期望值与实际值 Debug 格式间的差异!
这些宏同样支持自定义消息参数,与 `std::assert!(...)` 完全兼容。
这意味着您可将其作为直接替代品导入使用:
```
use assert2::assert;
```
## 示例
查看表达式及其求值结果:
```
check!(6 + 1 <= 2 * 3);
```

查看期望值与实际值间的多行差异:
```
check!(scrappy == coco);
```

或针对短数值的内联高亮显示:
```
check!((3, Some(4)) == [1, 2, 3].iter().size_hint());
```

测试模式匹配:
```
check!(let Ok(_) = File::open("/non/existing/file"));
```

从模式中捕获变量以供后续使用:
```
assert!(let Err(e) = File::open("/non/existing/file"));
check!(e.kind() == ErrorKind::PermissionDenied);
```

在单个宏中通过 `&&` 链运行多项检查(同时支持 `let` 链):
```
assert!(
let Err(e) = File::open("/non/existing/file")
&& e.kind() == ErrorKind::PermissionDenied
);
```

## `assert` 与 `check` 的区别
该库提供两个宏:`check!(...)` 和 `assert!(...)`。
主要区别在于 `check` 专为测试用例设计,不会立即引发 panic。
它会打印断言错误信息并标记测试失败。
这使您能够运行多项检查,更轻松地定位测试失败原因。
而 `assert` 宏仅打印错误信息后立即 panic,
同样可在非测试场景中使用。
当前实现中,`check` 通过作用域守卫延迟 panic 直至当前作用域结束。
理想情况下,`check` 根本不应触发 panic,仅标记测试用例失败。
若未来支持此特性,`check` 宏将相应调整,因此**不应依赖 `check` 触发 panic**。
## 稳定版与夜间版的差异
若可用,该库会使用 `proc_macro_span` 特性获取原始源代码。
在稳定版和测试版中,将回退至表达式字符串化处理。
这使得夜间版输出更具可读性。
## 变量捕获
使用 [`assert!(...)`](macro.assert.html) 宏时,`let` 模式中的占位符将被捕获。
它们会像常规 `let` 绑定一样在调用作用域中可用。
这使您能够对捕获的变量执行额外检查。
例如:
```
assert!(let Ok(foo) = Foo::try_new("bar"));
check!(foo.name() == "bar");
assert!(let Err(Error::InvalidName(e)) = Foo::try_new("bogus name"));
check!(e.name() == "bogus name");
check!(e.to_string() == "invalid name: bogus name");
```
[`check!(...)`](macro.check.html) 宏不具备此功能,因为即使检查失败,宏后的代码仍会继续执行。
但您可通过 `let` 链在同一宏调用中运行多项检查:
```
check!(let Ok(foo) = Foo::try_new("bar") && foo.name() == "bar");
check!(
let Err(Error::InvalidName(e)) = Foo::try_new("bogus name")
&& e.name() == "bogus name"
&& e.to_string() == "invalid name: bogus name"
);
```
## 控制输出格式
作为终端用户,您可通过修改 `ASSERT2` 环境变量调整 `assert2` 格式化失败断言的方式。
支持使用逗号分隔的任意选项组合。
可用选项包括:
* `auto`:根据断言长度自动选择紧凑或美观 `Debug` 格式(默认)。
* `pretty`:始终使用美观 `Debug` 格式(`{:#?}`)。
* `compact`:始终使用紧凑 `Debug` 格式(`{:?}`)。
* `no-color`:即使输出至终端也禁用彩色输出。
* `color`:即使输出未指向终端也启用彩色输出。
例如,可通过以下命令强制使用紧凑 `Debug` 格式并启用彩色输出:
```
ASSERT2=compact,color cargo test
```
若未设置 `color` 或 `no-color` 选项,
`assert2` 将遵循 [clicolors 规范](https://bixense.com/clicolors/):
* `NO_COLOR != 0` 或 `CLICOLOR == 0`:输出不带颜色代码的纯文本。
* `CLICOLOR != 0`:当输出指向终端时显示彩色输出。
* `CLICOLOR_FORCE != 0`:即使输出未指向终端也强制显示彩色输出。
标签:Cargo包, pocsuite3, Rust语言, 单元测试, 可视化界面, 威胁情报, 宏编程, 差异比较, 开发者工具, 彩色输出, 断言宏, 检查宏, 模式匹配, 测试框架, 编程库, 自动化资产收集, 软件测试, 通知系统, 错误报告, 默认DNS解析器