trybuild

trybuild

Rust编译器测试框架Trybuild

Trybuild是一个Rust测试框架,用于验证编译器错误消息。它主要用于测试过程宏的错误报告,通过比较预期和实际的编译器输出来确保错误信息的用户友好性。Trybuild支持编译失败和成功测试,提供简洁的API和便捷的工作流程,适用于各种Rust项目的编译器输出测试。

TrybuildRust测试工具编译错误测试用例Github开源项目

Trybuild

<img alt="github" src="https://img.shields.io/badge/github-dtolnay/trybuild-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20"> <img alt="crates.io" src="https://yellow-cdn.veclightyear.com/ab5030c0/79cd5831-5b1f-4d4f-b0ff-3cd9b4b7cec1.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20"> <img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-trybuild-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20"> <img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/trybuild/ci.yml?branch=master&style=for-the-badge" height="20">

Trybuild 是一个测试工具,用于在一组测试用例上调用 rustc 并断言产生的任何错误消息是预期的。

<p align="center"> <a href="#compile-fail-tests"> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/b68ce6ae-6262-420c-b31b-98758f4bd4b1.png" width="600"> </a> </p>

这种测试通常用于测试涉及过程宏的错误报告。我们会编写触发宏检测到的错误或 Rust 编译器在生成的展开代码中检测到的错误的测试用例,并与预期的错误进行比较,以确保它们保持用户友好。

这种测试风格有时被称为 ui 测试,因为它们测试了用户与库交互的方面,这些方面不会被普通的 API 测试所覆盖。

这里没有什么是特定于宏的;trybuild 同样适用于测试非宏 API 的误用。

[dev-dependencies] trybuild = "1.0"
<br>

编译失败测试

一个最小的 trybuild 设置如下所示:

#[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); }

可以使用 cargo test 运行测试。它会单独编译匹配全局模式的每个源文件,期望它们编译失败,并断言编译器的错误消息与相邻的 *.stderr 文件中包含的预期输出相匹配(与测试文件同名但扩展名不同)。如果匹配,则认为测试用例成功。

项目 Cargo.toml 中 [dev-dependencies] 下列出的依赖项可以在测试用例中访问。

失败的测试会内联显示预期与实际的编译器输出对比。

<p align="center"> <a href="#compile-fail-tests"> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/cc41a6ec-c8d5-470b-8c00-9fb97d0af420.png" width="600"> </a> </p>

未能编译失败的 compile_fail 测试也是一种失败。

<p align="center"> <a href="#compile-fail-tests"> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/2c277109-a27e-437a-957a-0ade8d36758b.png" width="600"> </a> </p>

要测试单个源文件,请使用:

cargo test -- ui trybuild=example.rs

其中 ui 是调用 trybuild#[test] 函数的名称,example.rs 是要测试的文件名。

<br>

通过测试

同样的测试工具也能运行预期通过的测试。通常你会让 Cargo 直接运行这些测试,但能够像这样组合模式可能对工作坊很有用,参与者可以一次启用一个测试用例。Trybuild 最初是为我在 Rust Latam 举办的过程宏工作坊开发的。

#[test] fn ui() { let t = trybuild::TestCases::new(); t.pass("tests/01-parse-header.rs"); t.pass("tests/02-parse-body.rs"); t.compile_fail("tests/03-expand-four-errors.rs"); t.pass("tests/04-paste-ident.rs"); t.pass("tests/05-repeat-section.rs"); //t.pass("tests/06-make-work-in-function.rs"); //t.pass("tests/07-init-array.rs"); //t.compile_fail("tests/08-ident-span.rs"); }

如果通过测试成功编译并具有在执行编译后的二进制文件时不会崩溃的 main 函数,则认为测试通过。

<p align="center"> <a href="#pass-tests"> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/776727b9-7eb7-4628-b2a5-6c5ca10d3e37.png" width="600"> </a> </p> <br>

详情

这就是整个 API。

<br>

工作流程

更新 *.stderr 文件有两种方法,在您迭代测试用例或库时不建议手动编写。

首先,如果一个测试用例作为 compile_fail 运行,但相应的 *.stderr 文件不存在,测试运行器会将实际的编译器输出保存到包含 Cargo.toml 的目录中名为 wip 的子目录中,并使用正确的文件名。因此,您可以通过删除这些文件,运行 cargo test,然后将 wip 中的所有文件移动到您的测试用例目录来更新这些文件。

<p align="center"> <a href="#workflow"> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/c8ba4b39-196d-430e-9fc9-096d5b0693ed.png" width="600"> </a> </p>

或者,使用环境变量 TRYBUILD=overwrite 运行 cargo test,跳过 wip 目录,直接将所有编译器输出写入原位置。之后您需要检查 git diff 以确保编译器的输出符合您的预期。

<br>

测试内容

对于编译失败测试,为任何您关心的、可能因用户面向的编译器输出变化而发生变化的内容编写测试。作为反面例子,请不要仅仅为了使用错误类型的参数调用所有公共 API 而编写编译失败测试;这样做没有任何好处。

一个常见的用途是测试过程宏发出的特定目标错误消息。例如,ref-cast crate 中的派生宏要求放置在具有 #[repr(C)]#[repr(transparent)] 的类型上,以确保展开不会产生未定义行为,这在编译时强制执行:

error: RefCast trait requires #[repr(C)] or #[repr(transparent)] --> $DIR/missing-repr.rs:3:10 | 3 | #[derive(RefCast)] | ^^^^^^^

使用辅助属性的宏需要检查这些属性中无法识别的内容是否正确地指示给调用者。错误消息是否正确放置在错误的标记下,而不是放在无用的 call_site span 上?

error: unknown serde field attribute `qqq` --> $DIR/unknown-attribute.rs:5:13 | 5 | #[serde(qqq = "...")] | ^^^

声明性宏也可以从编译失败测试中受益。serde_json 中的 json! 宏只是一个大型的 macro_rules 宏,但它努力确保输入中的错误 JSON 始终在最合适的标记上显示错误消息:

error: no rules expected the token `,` --> $DIR/double-comma.rs:4:38 | 4 | println!("{}", json!({ "k": null,, })); | ^ no rules expected this token in macro call

有时我们可能有一个成功展开的宏,但我们指望它在宏展开之后的某个点触发特定的编译器错误。例如,readonly crate 引入了公开但只可读的结构体字段,即使调用者有对周围结构体的 &mut 引用。如果有人写入只读字段,我们需要确保它不会编译:

error[E0594]: cannot assign to data in a `&` reference --> $DIR/write-a-readonly.rs:17:26 | 17 | println!("{}", s.n); s.n += 1; | ^^^^^^^^ cannot assign

在所有这些情况下,编译器的输出可能会因为我们的 crate 或其中一个依赖项破坏了某些内容,或者由于 Rust 编译器的变化而改变。这两种情况都是拥有精心设计的编译失败测试的好理由。如果我们重构并不小心导致原本正确的错误不再被发出或在错误的地方发出,测试套件捕捉到这一点很重要。如果编译器的变化使我们关心的错误消息大幅恶化,捕捉到这一点并报告为编译器问题也很重要。

<br>

许可证

<sup> 根据 <a href="LICENSE-APACHE">Apache License, Version 2.0</a> 或 <a href="LICENSE-MIT">MIT license</a> 两者之一授权,由您选择。 </sup> <br> <sub> 除非您另有明确说明,否则您有意提交以包含在本 crate 中的任何贡献(如 Apache-2.0 许可证中所定义)均应按上述方式双重许可,无任何附加条款或条件。 </sub>

编辑推荐精选

TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
商汤小浣熊

商汤小浣熊

最强AI数据分析助手

小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。

imini AI

imini AI

像人一样思考的AI智能体

imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。

Keevx

Keevx

AI数字人视频创作平台

Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。

即梦AI

即梦AI

一站式AI创作平台

提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作

扣子-AI办公

扣子-AI办公

AI办公助手,复杂任务高效处理

AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!

蛙蛙写作

蛙蛙写作

AI小说写作助手,一站式润色、改写、扩写

蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。

AI辅助写作AI工具蛙蛙写作AI写作工具学术助手办公助手营销助手AI助手
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
下拉加载更多