测试 Rust 代码

本文档介绍了编写 Rust 代码测试的最佳实践。 如需了解如何定义测试软件包和组件并运行它们,另请参阅组件测试指南,其中提供了 相关说明。

本文档面向在 fuchsia.git 中工作的开发者,所描述的工作流不太可能适用于 IDK 使用者。

本教程的源代码位于 //examples/hello_world/rust

单元测试

向代码添加测试

添加 Rust 单元测试的惯用方式在 Fuchsia 内外都适用,只需将以下代码段放入您要编写的任何测试的底部即可轻松完成:

#[cfg(test)]
mod tests {
    #[fuchsia::test]
    fn it_works() {
        assert_eq!(true, true);
    }
}

这会导致创建一个名为 tests 的新 mod,并且此 mod 仅在构建单元测试时包含。任何使用 #[fuchsia::test] 注解的函数都将作为测试运行,如果该函数成功返回,则测试通过。

#[fuchsia::test] 还支持执行异步代码的测试。

#[fuchsia::test]
async fn my_test() {
    let some_future = async { 4 };
    assert_eq!(some_future.await, 4);
}

典型的 #[test] 注解也适用,但它不支持异步测试或开箱即用的日志记录。如果您认为 crate 可能会在 Fuchsia 代码库之外使用,请优先使用 #[test]

构建测试

单元测试可以由 Rust 目标(即 rustc_binaryrustc_library)自动构建。这两种方法大体相似。

为 Rust 二进制文件构建测试

如果您要测试 Rust 二进制文件(即您有一个 main.rs),则本部分非常有用。如果您有库,请参阅下一部分。

您的 BUILD.gn 文件首先需要通过导入 rustc_binary 模板来使其可用:

import("//build/rust/rustc_binary.gni")

仅当添加了设置 with_unit_tests = true 时,rustc_binary GN 模板才会构建单元测试:

rustc_binary("bin") {
  name = "hello_world_rust"

  # Generates the "bin_test" build target
  with_unit_tests = true
  edition = "2024"

  deps = []
  test_deps = [ "//src/lib/fuchsia" ]

  sources = [ "src/main.rs" ]
}

设置 with_unit_tests = true 会导致此构建规则生成两个不同的可执行文件,一个使用提供的名称,另一个使用在提供的名称后附加 _bin_test 的名称。

在我们的示例中,创建的可执行文件名称如下:

  • hello_world_rust;以及
  • hello_world_rust_bin_test

为 Rust 库构建测试

您的 BUILD.gn 文件首先需要通过导入 rustc_library 模板来使其可用:

import("//build/rust/rustc_library.gni")

仅当添加了设置 with_unit_tests = true 时,rustc_library GN 模板才会构建单元测试,这与上述 rustc_binary 的情况类似。

不过,在这种情况下,系统会创建一个名称不同 的测试二进制文件:

  • hello_world_rust_lib_test。请注意,二进制文件的名称与库生成的名称不同 。

二进制文件名称非常重要,因为它们将在后续步骤中使用。

打包和运行测试

如需运行先前目标生成的测试,请将它们打包为测试组件 。测试组件包含一个 组件清单

您的 BUILD.gn 文件需要导入组件模板:

import("//build/components.gni")

您可以使用以下构建规则打包测试:

  • fuchsia_test_package():软件包模板,用于将多个测试组件及其依赖项收集到一个软件包中。 测试软件包通常用于集成测试。
  • fuchsia_unittest_package():用于包含单元测试的软件包的专用模板。单元测试软件包可以为不需要任何功能的单元测试生成最小的组件清单。

对于 Hello World 二进制文件示例,单元测试软件包引用 生成的 bin_test 目标(基于目标名称 bin 和隐式 后缀 _test)和 hello_world_rust_bin_test(基于 name 节的值)。

fuchsia_unittest_package("hello-world-rust-tests") {
  deps = [ ":bin_test" ]
}

如需运行测试,请运行:

fx test hello-world-rust-tests

如需了解如何打包和运行测试,请参阅 测试组件构建组件

实用 crate

以下树内第三方 crate 可帮助您编写测试:

  • assert_matches:提供宏 assert_matches!,使模式 断言符合人体工程学。
  • pretty_assertions:提供替代 assert_eq! 宏,该宏在断言失败时显示彩色 diff(差异比较)。

这些可以包含在 BUILD.gntest_deps 下。

rustc_binary("bin") {
  name = "my_test"
  with_unit_tests = true
  edition = "2024"

  test_deps = [
    "//third_party/rust_crates:matches",
    "//third_party/rust_crates:pretty_assertions",
  ]
}