Project Icon

trybuild

Rust编译器测试框架Trybuild

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

Trybuild

github crates.io docs.rs build status

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

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

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

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

[dev-dependencies]
trybuild = "1.0"

编译失败测试

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

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

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

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

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

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

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

cargo test -- ui trybuild=example.rs

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


通过测试

同样的测试工具也能运行预期通过的测试。通常你会让 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 函数,则认为测试通过。


详情

这就是整个 API。


工作流程

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

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

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


测试内容

对于编译失败测试,为任何您关心的、可能因用户面向的编译器输出变化而发生变化的内容编写测试。作为反面例子,请不要仅仅为了使用错误类型的参数调用所有公共 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 编译器的变化而改变。这两种情况都是拥有精心设计的编译失败测试的好理由。如果我们重构并不小心导致原本正确的错误不再被发出或在错误的地方发出,测试套件捕捉到这一点很重要。如果编译器的变化使我们关心的错误消息大幅恶化,捕捉到这一点并报告为编译器问题也很重要。


许可证

根据 Apache License, Version 2.0MIT license 两者之一授权,由您选择。
除非您另有明确说明,否则您有意提交以包含在本 crate 中的任何贡献(如 Apache-2.0 许可证中所定义)均应按上述方式双重许可,无任何附加条款或条件。
项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号