本文档介绍了针对 Rust 代码编写测试的最佳实践。您还可以参阅组件测试指南,了解有关定义测试软件包和组件并运行它们的说明。
本文档面向 fuchsia.git 内部的开发者,所描述的工作流程不太可能适用于 IDK 使用者。
本教程的源代码可在 //examples/hello_world/rust 中找到。
单元测试
向代码添加测试
添加 Rust 单元测试的惯用方式在 Fuchsia 内部和外部同样适用,只需将以下代码段放入您要编写的任何测试的底部,即可轻松完成:
#[cfg(test)]
mod tests {
#[fuchsia::test]
fn it_works() {
assert_eq!(true, true);
}
}
这会创建一个名为 tests 的新模块,并且该模块仅在构建单元测试时包含在内。任何带有 #[fuchsia::test] 注解的函数都将作为测试运行,如果该函数成功返回,则测试通过。
#[fuchsia::test] 还支持测试异步代码。
#[fuchsia::test]
async fn my_test() {
let some_future = async { 4 };
assert_eq!(some_future.await, 4);
}
典型的 #[test] 注释也适用,但它不支持异步测试或开箱即用的日志记录。如果您认为箱子可能会在 Fuchsia 代码库之外使用,请优先选择 #[test]。
编译测试
单元测试可以由 Rust 目标(即 rustc_binary 或 rustc_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 会导致此 build 规则生成两个不同的可执行文件,一个具有提供的名称,另一个具有附加到所提供名称的 _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。请注意,二进制文件的名称与库生成的名称不同。
二进制文件名称非常重要,因为它们将在后续步骤中使用。
将单元测试限制为主机或 Fuchsia
默认情况下,with_unit_tests = true 会在评估 BUILD.gn 文件的每个工具链中定义 <target_name>_test 目标。如需仅针对某些平台定义它,请将 with_unit_tests 设置为以下字符串之一,这些字符串与 Bazel Rust 宏的接口相匹配:
"host":仅在宿主工具链中定义测试目标。"fuchsia":仅在 Fuchsia 工具链中定义测试目标。"both":在主机和 Fuchsia 工具链中定义测试目标。
例如,如需仅在主机上构建和运行库的单元测试,请执行以下操作:
rustc_library("lib") {
name = "my_lib"
edition = "2024"
with_unit_tests = "host"
sources = [ "src/lib.rs" ]
}
group("tests") {
testonly = true
deps = [ ":lib_test($host_toolchain)" ]
}
打包和运行测试
如需运行之前由目标生成的测试,请将它们打包为测试组件。测试组件包含声明测试所需功能的组件清单。
您的 BUILD.gn 文件需要导入组件模板:
import("//build/components.gni")
您可以使用以下 build 规则打包测试:
fuchsia_test_package():一种软件包模板,用于将多个测试组件及其依赖项收集到一个软件包中。测试软件包通常用于集成测试。fuchsia_unittest_package():包含单元测试的软件包的专用模板。单元测试软件包可以为没有必需功能的单元测试生成最小组件清单。
对于 Hello World 二进制文件示例,单元测试软件包会引用生成的目标 bin_test(基于目标名称 bin 和隐式后缀 _test)和 hello_world_rust_bin_test(基于 name stanza 的值)。
fuchsia_unittest_package("hello-world-rust-tests") {
deps = [ ":bin_test" ]
}
如需运行测试,请运行以下命令:
fx test hello-world-rust-tests实用 crate
以下树内第三方箱可帮助您编写测试:
assert_matches:提供宏assert_matches!,使模式断言更符合人体工程学。pretty_assertions:提供了一个替代assert_eq!宏,可在断言失败时显示彩色 diff(差异比较)。
这些信息可包含在 test_deps 下的 BUILD.gn 中。
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",
]
}