oli-obk/ui_test
GitHub: oli-obk/ui_test
一个用于测试 Rust 编译器诊断输出的框架,帮助库作者验证错误信息在用户眼中的呈现效果。
Stars: 39 | Forks: 36
一个测试运行器,它使用 rustc 或 cargo(或任何其他编译器,需要一些配置工作)构建测试,并将编译器的输出与您提交到 git 的文件进行比较。这允许您测试当库被错误使用并发出错误时,您的库在用户眼中的显示效果。
## 用法
请参阅 [examples 目录](examples) 了解如何在您自己的 crate 中使用它。
为了能够通过 `cargo test` 使用它,您需要将
```
[[test]]
name = "your_test_file"
harness = false
```
放入您的 `Cargo.toml`,否则 `cargo test` 只会查找 `#[test]`,而不会运行实际上执行 `ui_test` 的 `fn main()`
## 隐式(可能令人惊讶)的行为
* 测试按其文件名的顺序运行(先文件,然后递归进入文件夹)。
因此,如果您有任何缓慢的测试,请在前面加上一个小整数,以便让它们尽可能早地运行,充分利用并行性(而不是等到最后才运行缓慢的测试)。
* `cargo test --test your_test_name -- --help` 列出了您可以指定的用于过滤、blessing(自动更新输出)和减少测试详细程度的命令。
* 由于 `cargo test` 本身会运行所有测试,因此单独使用 `cargo test -- --check` 将不起作用,但 `cargo test -- --quiet` 和 `cargo test -- some_test_name` 可以正常工作,因为 CLI 匹配机制不同。
* 如果存在与测试文件名相同的 `.stdin` 文件,它将作为标准输入通过管道传输到您的程序中。
## 支持的注释
如果您的测试预期失败,您需要在发生错误的地方添加 `//~` 注释
以确保测试始终在注释行失败。这将匹配错误的任何子字符串。这些注释可以采用两种形式:
* `//~ LEVEL: XXX` 按错误级别和消息文本匹配
* `LEVEL` 可以是以下之一(按降序排列):`ERROR`、`HELP`、`WARN`、`NOTE` 或 `ICE`
* 如果显式指定了级别,则该级别或更高级别的*所有*诊断都需要注释。为避免这种情况,请参阅 `//@require-annotations-for-level`
* 这将在标准化*之前*检查输出,因此您可以检查被标准化掉的内容,但需要注意不要意外使用在不同平台之间有差异的模式。
* 如果 `XXX` 的形式为 `/XXX/`,则将其视为正则表达式而不是子字符串,如果正则表达式匹配则成功。
* `//~ CODE` 按诊断代码匹配。
* `CODE` 可以采用多种形式,例如:`E####`、`lint_name`、`tool::lint_name`。
* 这只会匹配 `ERROR` 级别的诊断。
可以使用 `v`/`^` 将注释放置在与错误位置不同的行上:
```
causes_some_error()
//~^ some_error
//~v some_error
causes_some_error()
```
通过将这些符号重复 `n` 次,可以注释距离 `n` 行的错误:
```
causes_some_error()
//~^^ some_error
```
如果同一行有多个错误,注释可以放在连续的行上,并用 `|` “链接”:
```
causes_some_error_and_other_error()
//~^ some_error
//~| other_error
```
为了更改单个测试的测试方式,您可以在测试中添加各种 `//@` 注释。
任何其他注释将被忽略,并且所有 `//@` 注释必须严格按照其命令指定的格式进行,否则测试将在甚至未运行之前就失败。
* `//@ignore-C` 在满足条件 `C` 时避免运行测试。
* `C` 可以是 `target: XXX YYY`,它检查目标三元组是否包含 `XXX` 或 `YYY`。
* `C` 可以是 `host: XXX YYY`,它检查主机三元组是否包含 `XXX` 或 `YYY`。
* `C` 也可以是 `bitwidth:` 后跟一个或多个以空格分隔的整数大小,如 `64`、`32` 或 `16`。
* `C` 也可以是 `on-host`,这将仅在交叉编译测试期间运行测试。
* `//@only-C` **仅**在满足条件 `C` 时运行测试。条件与 `ignore` 相同。
* `//@needs-asm-support` **仅**在目标支持 `asm!` 时运行测试。
* `//@stderr-per-bitwidth` 为每个位宽生成一个 stderr 文件,因为它们有时可能差异很大
* `//@error-in-other-file: XXX` 可用于检查由于在其他文件中报告而无法使用 `//~` 模式的错误。
* `//@revisions: XXX YYY` 对列表中的每个以空格分隔的名称运行一次测试
* 为每个 revision 生成一个 stderr 文件
* 可以通过在 `~` 后的方括号中添加 revision 名称,将 `//~` 注释限制为特定的 revision:`//~[XXX]`
* 可以通过在 `@` 后的方括号中添加 revision 名称,将 `//@` 注释限制为特定的 revision:`//@[XXX]`
* 请注意,您不能向 `revisions` 命令添加 revisions。
例如:
//@revisions: edition2021 edition2024
//@[edition2021] edition:2021
//@[edition2024] edition:2024
//@[edition2024] check-pass
// Then in code:
let x = 12; //~[edition2021] dead_code
let x = 12;
//~[edition2021]^ dead_code
* `//@compile-flags: XXX` 将 `XXX` 附加到传递给 rustc 驱动程序的命令行参数中
* 您可以多次指定此项,所有 flags 都会累积
* `//@rustc-env: XXX=YYY` 将 rustc 驱动程序执行的环境变量 `XXX` 设置为 `YYY`。
* 对于 Miri,这些环境变量在通过 rustc 编译期间和程序模拟期间使用
* 您可以多次指定此项,累积所有环境变量
* `//@normalize-stdout-test: "REGEX" -> "REPLACEMENT"` / `//@normalize-stderr-test: "REGEX" -> "REPLACEMENT"` 将 stdout/stderr 中 `REGEX` 的所有匹配项替换为 `REPLACEMENT`。替换可以指定 `$1` 和类似的反向引用以粘贴捕获组。请注意,这不适用于 `//~` 注释指定的错误字符串。
* 您可以指定多个此类命令,无需创建单个正则表达式来处理您想要执行的多个替换。
* `//@require-annotations-for-level: LEVEL` 可用于更改需要相应注释的诊断级别。
* 这仅在存在任何类似 `HELP`、`WARN` 或 `NOTE` 的注释时才有用,因为它们会自动要求同一级别或更高级别的所有其他诊断都有注释。
* `//@check-pass` 要求测试没有错误注释,不发出错误,并以退出/状态代码 0 成功退出。
* `//@edition: EDITION` 将默认 edition (2021) 覆盖为给定的 edition。
* `//@no-rustfix` 不要对具有机器可应用建议的测试运行 [rustfix]。
* `//@aux-build: filename` 在 `auxiliary` 目录(测试目录内)中查找文件,将其编译为库并将当前 crate 链接到它。这允许您使用 `extern crate` 或仅通过 `use` 语句导入 crate。这将自动检测作为 proc macros 的 aux 文件并将它们构建为 proc macros。
* `//@run` 编译测试并运行生成的二进制文件。生成的二进制文件必须成功退出。Stdout 和 stderr 取自生成的二进制文件。编译期间的任何警告都将被忽略。
* 您还可以指定预期的不同退出代码/状态,例如 `//@run: 1` 或 `//@run: 101`(后者是 Rust panic 的标准退出代码)。
* run 测试将运行输出分别收集到 `.run.stderr` 和 `.run.stdout` 中。
* 如果存在 `.run.stdin` 文件,它将作为标准输入通过管道传输到测试的执行中。
## 与 compiletest-rs 的显著差异
* 目标选择是通过 `ignore-target: xxx` 和 `only-target: xxx` 完成的,而不是 compiletest 的
`ignore-xxx`/`only-xxx`。`xxx` 也必须是目标三元组的子字符串;不支持 compiletest 中的特殊集合(如 `macos`/`unix`)。
* 仅支持 `ui` 测试
* 测试按命名顺序运行,因此您可以为缓慢的测试加上 `0` 前缀,以便让它们先运行
* `aux-build` 需要显式指定嵌套的 aux builds,并且不允许您引用同级 `aux-build` 的产物。
标签:Cargo, Rust, Rustc, TDD, UI测试, 云安全监控, 可视化界面, 威胁情报, 开发者工具, 快照测试, 测试框架, 测试运行器, 编程语言工具, 编译器测试, 网络流量审计, 诊断输出, 通知系统, 通知系统, 错误处理, 静态分析