本文件將標準化我們在 GN 建構系統中定義與組織 FIDL 測試的方式,並遵循下列目標:
- 名稱一致:如果 Rust 使用
fx test fidl_rust_conformance_tests
,則 Go 應使用fx test fidl_go_conformance_tests
。一致且可預測的命名方式可以提供更優質的開發人員體驗。 - 執行所需操作。測試工作流程應可讓您輕鬆執行單一測試元件,而不必建構或執行任何其他項目。
- 在主機上執行。請盡可能讓測試支援在主機 (非 Fuchsia) 上執行,因為編輯建構執行的週期通常更快。
- 遵循最佳做法。您應遵循 Fuchsia 最佳做法,瞭解使用
fx test
、建構元件等。
術語
本文件使用下列術語:
- target:BUILD.gn 檔案中定義的 GN 目標
- toolchain:請參閱
fx gn help toolchain
- host:開發人員的平台,尤其是 linux 或 mac
- device:Fuchsia 平台,可以是實體或模擬 (例如 qemu)
- 套件:Fuchsia 套件;Fuchsia 的發行單位
- 元件:Fuchsia 元件;Fuchsia 中的可執行軟體單位
命名
一般原則:
- 請使用底線,不要使用連字號。
- 結尾為複數
_tests
,而非單數_test
。 - 針對套件、元件和二進位檔,請使用具描述性的完整名稱。
最後一步代表偏好使用全名 (例如 fidl_rust_conformance_tests
),而非 conformance_tests
等情境相關名稱。在目錄、套件、元件和二進位檔層級重複「fidl」和「rust」,看起來好像很複雜,而且看起來很冗長。但實際上,這些名稱不得重複,而且最好保持名稱不重複,而不要記住像 fidl-bindings-test
這樣的奇怪規則,fidl-test
代表 Dart,fidl-test
則代表 C。
名稱應採用以下配置,以底線連接部分:
tool [ bindings ] [ category [ subcategory ] ] tests
其中 tool 為下列任一值:
- fidl:FIDL 執行階段支援
- fidlc:FIDL 編譯器前端
- fidlgen:FIDL 編譯器後端
- gidl、measure_tape 等工具:其他工具
其他部分包括:
- 繫結
- 可以是 c、cpp、cpp_wire、hlcpp、rust、go、dart
- category、subcategory
- 範例類別:conformance、types、parser、lib
- 「請勿」使用「前端」、「後端」、「繫結」 (工具) 來區分這些項目
階層圖
每個定義測試的 BUILD.gn 檔案都應包含一個 "tests"
群組:
group("tests") {
testonly = true
deps = [ ... ] # not public_deps
}
如果目錄以「tests」結尾,且 BUILD.gn 檔案只定義測試目標,則該群組應改為與目錄名稱相符。例如,foo_tests/BUILD.gn 可以使用 group("foo_tests")
。這可讓 GN 標籤簡寫 //path/to/foo_tests
(相當於 //path/to/foo_tests:foo_tests
)。
這些群組會匯總至父項目錄中的 BUILD.gn 檔案的「tests」群組。根「tests」群組 (針對部分程式碼集,例如 src/lib/fidl/BUILD.gn) 應包含在 bundle/fidl/BUILD.gn。這樣做可讓 fx set ... --with //bundles/fidl:tests
在建構作業中納入所有 FIDL 測試。(由於 //bundles/buildbot/core
包含 //bundles/fidl:tests
,因此也會在 CQ 中執行測試)。
二進位檔名稱
通常測試二進位檔名稱是以目標名稱為基礎。舉例來說,test("some_tests") { ... }
目標會產生 some_tests
二進位檔。然而,如果是單一測試,您通常需要多個名稱不重複的多個目標 (來源集、元件、套件等)。因此,本文件中的範例使用目標名稱 (例如 some_tests_bin
),並使用 output_name
參數覆寫二進位檔名稱:
test("some_tests_bin") {
output_name = "some_tests"
...
}
這也適用於 rustc_test
、go_test
等。
裝置測試
假設我們有可產生 fidl_foo_tests
二進位檔的 :fidl_foo_tests_bin
目標,如要將此套件納入套件,請使用 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
二進位檔的 :fidl_bar_tests_bin
目標,我們必須確保 GN 在達到該目標時位於 $host_toolchain
中,否則就會嘗試為 Fuchsia 建構 GN:
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"
}
由於 tests.json 中的「name」欄位,執行 fx test fidl_bar_tests
能夠正常運作。
主機/裝置測試
在主機和裝置上執行的測試分為兩類。在第一個類別中,測試目標只會在其中一個工具鍊下建構。例如:
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_lib_test
二進位檔的 baz_test
目標。請勿使用此情況,原因有二:
與其使用 with_unit_tests
,您需使用適當的名稱分別撰寫 rustc_test
目標:
rustc_library("baz") {
...
}
rustc_test("fidl_baz_tests") {
...
}
分組
假設我們的測試結構如下:
- FIDL Rust
- 裝置
- 合規
- 整合
- 主機
- 合規
- 裝置
葉子應有測試目標:
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