FIDL 测试和 GN

本文档规范了我们在 GN 中定义和组织 FIDL 测试的方式。 构建系统,并遵循以下目标:

  • 名称一致。如果 Rust 使用 fx test fidl_rust_conformance_tests, 那么 Go 应使用 fx test fidl_go_conformance_tests。一致且 可预测的命名方式可提供更好的开发者体验。
  • 运行您需要的内容。测试工作流应能轻松运行 单个测试组件,而无需构建或运行任何额外内容。
  • 在主机上运行。测试应尽可能支持在主机上运行 (非 Fuchsia),其中“编辑-构建-运行”的周期通常要短得多。
  • 遵循最佳做法。我们应该遵循 Fuchsia 最佳实践, 使用 fx test建筑物组件

术语

本文档使用以下术语:

  • target:在 BUILD.gn 文件中定义的 GN 目标
  • 工具链:请参阅 fx gn help toolchain
  • host:开发者的平台,特别是 linux 或 mac
  • device:Fucsia 平台,可以是物理平台,也可以是模拟平台(即 qemu)
  • packageFuchsia 软件包;分布单位为 紫红色
  • component:一个 Fuchsia 组件;可执行软件单元 紫红色

命名

通用准则:

  • 请使用下划线,不要使用连字符。
  • 以复数 _tests 而非单数 _test 结束名称。
  • 对软件包、组件和二进制文件使用完整的描述性唯一名称。

最后一点意味着建议你使用全名,例如 fidl_rust_conformance_tests 上下文名称,例如 conformance_tests。这看起来可能很冗长 重复“fidl”是多余的和“锈”目录、软件包和组件 二进制数。但事实上,这些名称必须是唯一的,最好是 使它们以一致的方式与众不同,而不是记住诸如此类的奇怪规则 fidl-bindings-test 适用于 Dart,而 fidl-test 适用于 C。

名称应使用以下架构,使用下划线连接各个部分:

工具 [ bindings ] [ 类别 [ 子类别 ] ] 测试

其中,tool 可以是以下其中一项:

  • fidl:FIDL 运行时支持
  • fidlc:FIDL 编译器前端
  • fidlgen:FIDL 编译器后端
  • gidlmeasure_tape 等:其他工具

其他部分包括:

  • 绑定 <ph type="x-smartling-placeholder">
      </ph>
    • ccppcpp_wirehlcpprustgo dart
  • categorysubcategory <ph type="x-smartling-placeholder">
      </ph>
    • 类别示例:conformancetypesparserlib
    • 请勿使用:frontendbackendbindings (tool 区分这些内容)

层次结构

每个定义测试的 BUILD.gn 文件都应包含一个 "tests" 组:

group("tests") {
  testonly = true
  deps = [ ... ]  # not public_deps
}

如果目录以“tests”结尾,且 BUILD.gn 文件仅定义 test 目标,则群组应与目录名称匹配。例如: foo_tests/BUILD.gn 可以使用 group("foo_tests")。这会启用 GN 标签 简写 //path/to/foo_tests,相当于 //path/to/foo_tests:foo_tests

这些组汇总在“测试”中父级中的 BUILD.gn 文件组 目录。根“tests”(对于代码库的某些部分,例如 src/lib/fidl/BUILD.gn) 应包含在 bundle/fidl/BUILD.gn 中。这样一来, fx set ... --with //bundles/fidl:tests - 用于在 build 中包含所有 FIDL 测试。 (这些测试也会在 CQ 中运行,因为 //bundles/buildbot/core 包含 //bundles/fidl:tests。)

二进制文件名称

通常,测试二进制文件名称基于目标名称。例如, test("some_tests") { ... } 目标将生成一个 some_tests 二进制文件。 不过,对于单个测试,您通常需要多个目标(源代码集、 组件、软件包等)。因此,此部分中的示例 文档使用 some_tests_bin 等目标名称,并替换二进制文件名称 使用 output_name 参数:

test("some_tests_bin") {
  output_name = "some_tests"
  ...
}

这也适用于 rustc_testgo_test 等。

设备测试

假设我们有一个 :fidl_foo_tests_bin 目标,该目标会生成 fidl_foo_tests 二进制文件如需将此方法封装在软件包中,请使用 fuchsia_unittest_package

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

fuchsia_unittest_package("fidl_foo_tests") {
  deps = [ ":fidl_foo_tests_bin" ]
}

现在,我们可以按软件包名称或组件名称(两者相同)运行测试 尽在 fx test fidl_foo_tests

为每个测试使用单独的软件包。如果不相关的测试组件 捆绑在一个软件包中,运行其中一个测试会导致整个软件包 重建。只有在满足以下条件时,您才能将多个测试组件捆绑到一个软件包中: 一起进行测试,例如需要进行客户端和服务器集成测试请参阅 如需查看示例,请参阅复杂拓扑和集成测试

如果您的测试需要任何组件功能、服务等, fuchsia_unittest_component 默认值,您必须编写一个组件清单文件:

# BUILD.gn
import("//build/components.gni")

fuchsia_unittest_package("fidl_foo_tests") {
  manifest = "meta/fidl_foo_tests.cml"
  deps = [ ":fidl_foo_tests_bin" ]
}

# meta/fidl_foo_tests.cml
{
    program: {
        "binary": "bin/fidl_foo_tests"
    },
    use: [
      {
        protocol: [
          "fuchsia.logger.LogSink",   # some example services
          "fuchsia.process.Launcher"
        ]
      }
    ]
}

有关套件模板和组件模板的更多信息,请参见构建 组件

主机测试

假设我们有一个 :fidl_bar_tests_bin 目标,该目标会生成 fidl_bar_tests 二进制文件我们必须确保 GN 在$host_toolchain达到 target,否则它会尝试针对 Fuchsia 进行构建:

groups("tests") {
  testonly = true
  deps = [ ":fidl_bar_tests_bin($host_toolchain)" ]
}

(务必将 ($host_toolchain) 放入 BUILD.gn 文件的 tests 组中,而不是放在 //bundles/fidl:tests.)

这将创建一个名为 host_x64/fidl_bar_tests 的 test_spec 条目, 最终在 out/default/tests.json 中:

{
  "command": [ "host_x64/fidl_bar_tests", "--test.timeout", "5m" ],
  "cpu": "x64",
  "label": "//PATH/TO/BAR:fidl_bar_tests_bin(//build/toolchain:host_x64)",
  "name": "host_x64/fidl_bar_tests",
  "os": "linux",
  "path": "host_x64/fidl_bar_tests",
  "runtime_deps": "host_x64/gen/PATH/TO/BAR/fidl_bar_tests_bin.deps.json"
}

由于“name”的原因,可以运行 fx test fidl_bar_tests字段中的 tests.json.

主机/设备测试

同时在主机和设备上运行的测试分为两类。在第一个 则测试目标只需在任一工具链下构建即可。例如:

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

rustc_test("fidl_rust_conformance_tests_bin") {
  output_name = "fidl_rust_conformance_tests"              # host test name
  ...
}

fuchsia_unittest_package("fidl_rust_conformance_tests") {  # device test name
  deps = [ ":fidl_rust_conformance_tests_bin" ]
}

group("tests") {
  testonly = true
  deps = [
    ":fidl_rust_conformance_tests_bin($host_toolchain)",
    ":fidl_rust_conformance_tests",
  ]
}

现在,我们可以通过两种方式运行测试:

  • 在以下设备上:fx test fidl_rust_conformance_tests --device
  • 在以下主机上:fx test fidl_rust_conformance_tests --host

第二类,设备测试和主机测试共享源代码,但它们 差异足够大,因此必须由单独的目标定义。这个 需要将主机测试定义封装在 if (is_host) { ... } 中, GN 抱怨多个目标会产生相同的输出。例如:

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

source_set("conformance_test_sources") {
  ...
}

test("fidl_hlcpp_conformance_tests_bin") {
  output_name = "fidl_hlcpp_conformance_tests"
  ...
  deps = [
    ":conformance_test_sources",
    ...
  ]
}

if (is_host) {
  test("fidl_hlcpp_conformance_tests_bin_host") {
    output_name = "fidl_hlcpp_conformance_tests"            # host test name
    ...
    deps = [
      ":conformance_test_sources",
      ...
    ]
  }
}

fuchsia_unittest_package("fidl_hlcpp_conformance_tests") {  # device test name
  deps = [ ":fidl_hlcpp_conformance_tests_bin" ]
}

group("tests") {
  testonly = true
  deps = [
    ":fidl_hlcpp_conformance_tests_bin_host($host_toolchain)",
    ":fidl_hlcpp_conformance_tests",
  ]
}

现在,我们可以通过两种方式运行测试:

  • 在以下设备上:fx test fidl_hlcpp_conformance_tests --device
  • 在以下主机上:fx test fidl_hlcpp_conformance_tests --host

Rust 单元测试

Rust 库的定义如下:

rustc_library("baz") {
  with_unit_tests = true
  ...
}

这会自动创建一个 baz_test 目标,用于构建 baz_lib_test 二进制文件请勿使用,原因有两个:

  1. 命名准则要求使用 _tests 后缀,而不是 _test
  2. 可能会让人感到困惑,并且可能在

请编写一个单独的 rustc_test 目标,并使用with_unit_tests 适当的名称:

rustc_library("baz") {
  ...
}

rustc_test("fidl_baz_tests") {
  ...
}

分组

假设我们有以下测试结构:

  • FIDL Rust <ph type="x-smartling-placeholder">
      </ph>
    • 设备 <ph type="x-smartling-placeholder">
        </ph>
      • 一致性
      • 集成
    • 托管者 <ph type="x-smartling-placeholder">
        </ph>
      • 一致性

我们应该为叶子设置测试目标:

  • fx test fidl_rust_conformance_tests
  • fx test fidl_rust_integration_tests

我们应该为运行各部分的不同而额外创建软件包 测试。使用 fx test,我们已经可以

  • 运行所有测试:fx test //path/to/fidl/rust
  • 运行所有设备测试:fx test //path/to/fidl/rust --device
  • 运行所有主机测试:fx test //path/to/fidl/rust --host

参考文档