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测试, 云安全监控, 可视化界面, 威胁情报, 开发者工具, 快照测试, 测试框架, 测试运行器, 编程语言工具, 编译器测试, 网络流量审计, 诊断输出, 通知系统, 通知系统, 错误处理, 静态分析