本文档介绍了为 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_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 = "2021"
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
。请注意,二进制文件的名称与库生成的名称不同。
二进制文件名称非常重要,因为它们会在后续步骤中使用。
打包并运行测试
如需运行由先前的目标生成的测试,请将它们打包为测试组件。您可以使用以下构建规则打包测试:
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!
宏,该宏会在断言失败时显示彩色差异。
这些内容可以添加到BUILD.gn
中的test_deps
下。
rustc_binary("bin") {
name = "my_test"
with_unit_tests = true
edition = "2021"
test_deps = [
"//third_party/rust_crates:matches",
"//third_party/rust_crates:pretty_assertions",
]
}