FIDL 測試與分析;GN

本文件將針對 GN 中 FIDL 測試的定義和整理方式進行標準化 建構系統,遵循下列目標:

  • 一致的名稱。如果 Rust 使用 fx test fidl_rust_conformance_tests, 接著,Go 應使用 fx test fidl_go_conformance_tests。一致且 且可預測的命名方式有助於提升開發人員體驗。
  • 執行所需工作。測試工作流程應該要能讓您輕鬆執行 只需一個測試元件即可,不必另外建構或執行任何額外項目。
  • 在主機上執行。應盡可能在主機上執行測試
  • 遵循最佳做法。我們應該遵循 Fuchsia 的最佳做法 使用 fx test建構元件

術語

本文件使用下列術語:

  • target:BUILD.gn 檔案中定義的 GN 目標
  • toolchain:請參閱 fx gn help toolchain
  • host:開發人員的平台,尤其是 Linux 或 mac
  • device:Fuchsia 平台,實體或模擬 (例如 qemu)
  • packageFuchsia 套件;分配單位 紫紅色
  • 元件Fuchsia 元件;可執行軟體的單位 紫紅色

命名

一般指南:

  • 請使用底線,而非連字號。
  • 結尾的名稱為複數 _tests,而非單數 _test
  • 為套件、元件和二進位檔使用完整且描述性的名稱。

最後重點是指更偏好全名,例如 fidl_rust_conformance_tests 與比對相關的名稱 (例如 conformance_tests) 相比這聽起來可能很冗長 重複「fidl」的冗餘和「rust」目錄、套件、元件和 二進位等級的資料。事實上,這些名稱不得重複 如此一來,就不會記住一些奇怪的規則 fidl-bindings-test 代表 Dart,fidl-test 代表 C。

名稱應採用以下配置,並以底線連接部分:

工具 [ bindings ] [ category [ subcategory ] ] 測試

其中 tool 是下列任一項目:

  • fidl:支援 FIDL 執行階段
  • fidlc:FIDL 編譯器前端
  • fidlgen:FIDL 編譯器後端
  • gidlmeasure_tape 等:其他工具

其他部分如下:

  • 繫結
    • 下列其中一個值:ccppcpp_wirehlcpprustgo飛鏢
  • categorysubcategory
    • 範例類別:conformancetypesparserlib
    • 請「不要」使用:前端後端繫結 (工具) 區別這些元素)

階層

每個定義測試的 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 檔案群組 目錄根層級的「測試」(適用於程式碼集的某部分,例如 src/lib/fidl/BUILD.gn) 應包含在 bundle/fidl/BUILD.gn 中。這樣一來, fx set ... --with //bundles/fidl:tests,用於在版本中加入所有 FIDL 測試。 (由於 //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 後 目標,否則會嘗試為 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"
}

由於「名稱」發生問題,因此執行 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 目標的獨立 rustc_test 目標,而不是 with_unit_tests 適當名稱:

rustc_library("baz") {
  ...
}

rustc_test("fidl_baz_tests") {
  ...
}

分組方式

假設我們的測試結構如下:

  • Rust 的 FIDL
    • 裝置
      • 合規
      • 整合
    • 代管者
      • 合規

我們應該針對葉子設立測試目標:

  • 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

參考資料