範圍
本文說明如何定義、建構及執行僅存在於 Bazel 圖中的測試。
Fuchsia 支援符合下列規定的 Bazel 主機測試:
這些測試必須只能使用 Bazel 建構,也就是說,測試不依賴先前 Ninja 叫用產生的構件。
這些測試只包含二進位檔和執行階段檔案,可在「未」連至任何 Fuchsia 裝置或模擬器的相容主機系統上執行。
Fuchsia 也支援 Bazel 裝置測試,這類測試是以 fx_test() 宣告,並在 Fuchsia 裝置或模擬器上執行。這些規則同樣必須只能使用 Bazel 建構,此外:
- 除了
environments(預設為建構作業的預設測試環境)、build_only、max_log_severity(預設為WARN) 和test_type(用於在非密封測試領域中執行,例如"starnix"或"system") 之外,測試規格欄位 (逾時等) 目前無法針對個別測試自訂。
fxbug.dev/564574581 會追蹤 Bazel 中目標測試的剩餘工作。
在 Bazel 中定義 Fuchsia 主機測試
一般 Bazel 測試規則 (例如 rustc_test、go_test) 與 Fuchsia 測試執行工具不相容。fx test 無法查看這些內容,基礎架構建構工具也不會執行這些內容。
因此,如要在 Bazel 中定義與 Fuchsia 相容的主機測試,請按照下列步驟操作:
使用
//build/bazel/rules/host_tests:host_<xxx>_test.bzl中的語言專屬主機測試包裝函式,例如host_rustc_test()、host_go_test()等。這些規則可直接取代一般 Bazel 測試規則,並提供
test_data、test_args等額外引數,讓 Fuchsia 測試執行工具能以正確的執行階段環境和引數叫用這些規則。只有在測試沒有特定語言的包裝函式時,才使用
//build/bazel/rules/host_tests:host_test.bzl的一般host_test()包裝函式。例如:load("//build/bazel/rules/host_tests:host_test.bzl", "host_test") load("@rules_sh//sh:sh_binary.bzl", "sh_binary") sh_binary( name = "test_bin", ... ) host_test( name = "shell_test", binary = ":test_bin", )如果是 C/C++ 測試,
host_cc_test()會使用fx_cc_test_binary()建構二進位檔,且不會在host_test()中新增任何其他內容。如要一併執行已封裝為主機端裝置測試的fx_cc_test_binary(),請使用host_test()包裝,而非從相同來源定義第二個二進位檔,例如在 Fuchsia 和主機工具鍊中建構的 GNtest():load("//build/bazel/platforms:constraints.bzl", "HOST_OS_CONSTRAINTS") load("//build/bazel/rules/host_tests:host_test.bzl", "host_test") host_test( name = "foo_unittests_host_test", binary = ":foo_unittests", target_compatible_with = HOST_OS_CONSTRAINTS, )請「勿」假設測試二進位檔的執行位置 (例如
out/default),因為測試二進位檔是從無法預測確切路徑的目錄啟動。Bazel 主機測試必須為封閉式,並明確列出所有執行階段依附元件,就像 GN 主機測試一樣。您可以透過下列其中一種機制提供執行階段依附元件:
做為
host_test_data_files()或host_test_data_map()目標的test_data依附元件 (請參閱//build/bazel/rules/host_tests:host_test_data.bzl)。這會讓檔案在執行階段時,在相對於測試執行目錄的固定位置可用,類似於 GNhost_test_data()範本。host_xxx_test()目標上的data屬性。在這種情況下,檔案會新增至測試的執行檔案,並可使用執行檔案程式庫存取。
請使用
test_suite()定義測試群組,而非filegroup()。測試套件可能依附於測試和其他測試套件。
將 Bazel 主機測試匯出至 fx test 和基礎架構建構工具
如果只定義 host_xxx_test() 目標,fx test 和基礎架構建構工具將「無法」看到該目標。
如要讓 fx test 和基礎架構建構工具看到 Bazel 主機測試,請在其套件中公開 "host_tests" test_suite(),將該套件套件納入區域匯總 test_suite() 目標,從相同目錄的 BUILD.gn 中的 bazel_test_suite() 參照匯總套件,並將該目標新增至 GN 中的 group("tests")。例如:
//src/foo/lib/parser/BUILD.bazel:
load("//build/bazel/platforms:constraints.bzl", "HOST_OS_CONSTRAINTS")
load("//build/bazel/rules/host_tests:host_rustc_test.bzl", "host_rustc_test")
test_suite(
name = "host_tests",
# Include all tests in the package. Only use `tests = []` when every test
# in the package belongs to this suite; if the package has both host and
# device tests, define both `"host_tests"` and `"tests"` and list each
# suite's tests explicitly.
tests = [],
visibility = ["//src/foo:__pkg__"],
)
host_rustc_test(
name = "parser_test",
srcs = ["src/lib.rs"],
edition = "2024",
target_compatible_with = HOST_OS_CONSTRAINTS,
)
//src/foo/BUILD.bazel:
test_suite(
name = "foo_host_tests",
tests = [
"//src/foo/lib/parser:host_tests",
"//src/foo/util:host_tests",
],
)
//src/foo/BUILD.gn:
import("//build/bazel/bazel_test_suite.gni")
bazel_test_suite("bazel_tests") {
host_tests = [
# This references the target in BUILD.bazel.
"//src/foo:foo_host_tests",
]
}
group("tests") {
testonly = true
deps = [
":bazel_tests",
...
]
}
這樣一來,Bazel 測試的項目就會顯示在 out/default/tests.json 中。如有疑問,請在 fx set 或 fx gen 之後檢查這個檔案的內容。Bazel 測試的 label 欄位開頭為 @。
在開發期間,您可以先建構並執行已定義的測試目標,再按照上述方式匯出。請參閱下方的「直接使用 Bazel 執行測試」一節。
最佳做法
如要瞭解建構 Bazel 測試和 test_suite() 目標的樣式和最佳做法,請參閱「測試和測試套件」。如要瞭解 bazel_test_suite() 如何連線至 GN 測試圖,以及從 GN 遷移測試時該怎麼做,請參閱「將 Bazel 測試掛接到 GN 測試圖」。
在 Bazel 中定義 Fuchsia 裝置測試
裝置測試是 Fuchsia 套件中的元件,與 GN 建構作業中的元件完全相同。使用 fx_test_component() 宣告測試元件,使用 fx_package() 封裝,並使用 fx_test() 將其公開為測試:
//src/foo/bar/BUILD.bazel:
load("//build/bazel/rules/packages:fx_packaged_binary.bzl", "fx_packaged_binary")
load(
"//build/bazel/rules/components:fx_component.bzl",
"fx_component_manifest",
"fx_test_component",
)
load("//build/bazel/rules/packages:fx_package.bzl", "fx_package")
load("//build/bazel/rules/testing:fx_test.bzl", "fx_test")
fx_packaged_binary(
name = "bar_test_packaged_bin",
testonly = True,
binary = ":bar_test_bin",
binary_name = "bar_test",
)
fx_component_manifest(
name = "bar_test_manifest",
testonly = True,
component_name = "bar_test",
includes = ["//src/sys/test_runners/gtest:default.shard.cml"],
manifest = "meta/bar_test.cml",
)
fx_test_component(
name = "bar_test_component",
compiled_manifest = ":bar_test_manifest",
deps = [":bar_test_packaged_bin"],
)
fx_package(
name = "bar_tests_package",
package_name = "bar_tests",
test_components = [":bar_test_component"],
)
fx_test(
name = "bar_tests",
package = ":bar_tests_package",
# Optional: defaults to the build's default test environments when omitted.
environments = [
"//build/testing/environments:aemu_env",
"//build/testing/environments:nuc11_env",
],
)
test_components 中的每個元件都會成為獨立測試,名稱為套件網址,例如 fuchsia-pkg://fuchsia.com/bar_tests#meta/bar_test.cm。
如要自訂測試執行的目標環境,請將 environments 以環境目標清單的形式傳遞至 fx_test()。//build/testing/environments 在 //build/testing/environments.gni 中為每個個別環境設定一個目標,並使用相同名稱 (例如 :emu_env 或 :nuc11_env)。如果省略 environments,測試會在建構作業的預設測試環境 (GN 的 basic_envs) 中執行,就像未設定 environments 的 GN 測試一樣。如要建構測試而不執行,請改為設定 build_only = True。
如要將基礎架構設定 (例如標記) 新增至其中一個環境,請使用 fx_test_environment_variant():
load(
"//build/bazel/rules/testing:fx_test_environment.bzl",
"fx_test_environment_variant",
)
fx_test_environment_variant(
name = "nuc11_isolated_env",
base = "//build/testing/environments:nuc11_env",
env_tags = ["e2e-isolated"],
)
新環境應該很少見;大多數測試都應使用 //build/testing/environments 中的現有環境之一。如需新環境,請將其新增至 //build/testing/environments.gni 和 //build/testing/environments/BUILD.bazel,而不是在測試旁使用 fx_test_environment() 定義。環境的 Swarming 維度是與基礎架構互動的介面,因此會集中保存在一處。
如要在非密封測試領域 (例如 "starnix"、"system" 或 "vulkan") 執行測試,請將 test_type 傳遞至 fx_test_component() (或傳遞至 fx_test(),套用至套件中的所有測試元件)。有效的 test_type 值與 //build/components/fuchsia_test_component.gni 中的 type_moniker_map 相符。
將 Bazel 裝置測試匯出至 fx test 和基礎架構建構工具
與主機測試一樣,請透過 "tests" test_suite() 公開套件中的裝置測試,將這些測試分組到區域匯總 test_suite() 目標,在同一目錄中 GN bazel_test_suite() 的 target_tests 列出匯總套件,然後將該目標新增至 GN 中的 group("tests") (請參閱「將 Bazel 測試掛接到 GN 測試圖表」):
//src/foo/BUILD.gn:
import("//build/bazel/bazel_test_suite.gni")
bazel_test_suite("bazel_tests") {
target_tests = [
# This references the aggregation test_suite() in //src/foo/BUILD.bazel.
"//src/foo:foo_tests",
]
}
group("tests") {
testonly = true
deps = [
":bazel_tests",
...
]
}
裝置測試與主機測試分開追蹤,因為裝置測試是在 fuchsia_platform Bazel 設定中查詢和建構,而不是在主機設定中。
除了 tests.json 項目外,這也會寫入 ${root_build_dir}/bazel_test_packages.list,列舉建構圖中所有 Bazel 測試套件的套件資訊清單。完整的 fx build 叫用會將這份清單合併至 all_package_manifests.list,並將其套件發布至 amber-files,而 fx test 也會在視需要建構特定測試目標時直接合併。
這份清單和 tests.json 項目 package_manifests 中的資訊清單,並非 Bazel 輸出基礎中的資訊清單。Bazel 建構測試套件後,建構作業會將其 blob 永久連結至 Ninja 建構目錄,並寫入指向這些 blob 的資訊清單副本 (請參閱 //build/bazel/scripts/bazel_test_packages.py)。Bazel 僅保證在要求叫用結束時,輸出內容會位於磁碟上,因此後續的 Bazel 叫用可能會刪除這些消費者需要的檔案。
將 Bazel 測試連結至 GN 測試圖
GN 和 Ninja 仍是建構作業的進入點 (特別是在基礎架構中;在某些本機工作流程中,例如使用 fx test 執行單一 Bazel 測試,建構作業會直接叫用 Bazel),因此任何 Bazel 測試目標都必須對 GN 可見,建構作業和 tests.json 才能納入該目標。每個 Bazel 測試都必須可從建構工具已觸及的 GN 目標連線:
fx_test() / host_xxx_test() (package BUILD.bazel)
<- package test_suite() (package BUILD.bazel: "tests" / "host_tests")
<- aggregation test_suite() (area BUILD.bazel, e.g. "foo_tests")
<- bazel_test_suite() (area BUILD.gn)
<- group("tests") (area BUILD.gn)
<- area groups such as //src:tests, then builder groups in //bundles/buildbot
沒有預先提交檢查會驗證 Bazel 測試是否具有這個路徑。如果這個路徑缺少任何連結,fx gen 和 fx build 會成功執行,不會顯示任何警告,且測試不會在基礎架構中建構或執行。新增測試後,請在建構作業中加入其 GN 測試群組 (例如使用 fx add-test //src/foo:tests,或將 --with-test //src/foo:tests 或 --with //bundles/buildbot/... 傳遞至 fx set 並執行 fx gen),並檢查測試的標籤 (開頭為 @) 是否顯示在 out/default/tests.json 中。請在測試應執行的建構設定中執行這項操作,因為 Bazel 也會自動略過與目前設定不相容的測試。
建構工具也可以透過 product_bundle_test_group()
中的 //bundles/buildbot 加入裝置測試,針對特定
產品組合 (而非建構工具的預設組合) 執行測試。這是一項額外機制,透過這種方式進行的測試仍需要 bazel_test_suite()。
建議的版面配置
測試和測試套件定義了建構 Bazel 測試和 test_suite() 目標的完整樣式規則。大致來說,測試套件會透過三個層級連結至 GN,而 GN 仍會驅動建構作業:
在每個有測試的套件中,公開
test_suite()套件。裝置測試請命名為"tests",主機測試則命名為"host_tests",並將個別*_test目標設為套件的私人目標 (預設),然後將套件組合的visibility設為匯總該套件組合的區域套件 (使用:__pkg__,絕不使用:__subpackages__)。請勿在套件的test_suite()中加入子套件的測試或test_suite()目標。將套件套件組合分組在區域匯總
test_suite()中,並與同一目錄BUILD.gn中的一個bazel_test_suite()配對。請盡量減少匯總套件,且不要在每個中繼目錄中重新建立 GN 的tests群組模式。選擇開發人員新增套件的層級,以及OWNERS核准套件的層級。舉例來說,請使用//src/connectivity/bluetooth,而非//src/connectivity,這樣新增藍牙套件時,就不需要取得連線範圍擁有者的核准。根據匯總範圍命名匯總test_suite()(結尾為"tests"或"host_tests"),僅列出其中的套件test_suite()目標,並在相符的BUILD.gn中使用bazel_test_suite()的完整//標籤參照://src/foo/bar/BUILD.bazel:test_suite( name = "tests", # Include all tests in the package. Only use `tests = []` when every test # in the package belongs to this suite; if the package has both device and # host tests, define both `"tests"` and `"host_tests"` and list each # suite's tests explicitly. tests = [], visibility = ["//src/foo:__pkg__"], ) # Private *_test target(s) in this package. ...//src/foo/BUILD.bazel:test_suite( name = "foo_tests", tests = [ "//src/foo/bar:tests", "//src/foo/baz:tests", ], )//src/foo/BUILD.gn:import("//build/bazel/bazel_test_suite.gni") bazel_test_suite("bazel_tests") { target_tests = [ "//src/foo:foo_tests" ] } group("tests") { testonly = true deps = [ ":bazel_tests", ... ] }如果現有區域匯總套件存在,請將新套件新增至該套件;否則,請與區域目錄擁有者達成協議,並在該目錄中新增匯總
test_suite()和bazel_test_suite()。較舊的區域套件 (例如//tools:host_tests) 仍會直接列出部分個別測試目標;請保留現有項目,並為新增或遷移的套件公開套件test_suite()。將主機和裝置測試分開。請將裝置測試套件放在
target_tests,主機測試套件放在host_tests,且不要在任何 Bazeltest_suite()中混用主機和裝置測試。否則建構作業會失敗,且/或測試會自動遭到捨棄。將每個匯總
test_suite()連結至 GN 測試圖表一次。從兩個bazel_test_suite()目標連到同一個 Bazel 測試套件,並不會執行兩次測試 (相同的tests.json項目會合併),但會使版面配置更難理解。
從 GN 遷移測試時
請勿為了將 Bazel 測試連結至 GN,而保留
BUILD.gn。如果目錄中的每個目標都移至 Bazel,且沒有 GN 目標依賴該目錄,請刪除其BUILD.gn,從父項BUILD.gn中移除已刪除目錄的:tests群組,並將套件的test_suite()新增至區域的匯總test_suite()。即使BUILD.gn仍保留給仍有 GN 依附元件的目標 (請參閱「在兩個建構系統中測試程式庫」),也請透過區域的匯總test_suite()連結 Bazel 測試套件,而非每個目錄的bazel_test_suite()。在bazel2gn同步處理檔案的BUILD.bazel檔案中,將# @bazel2gn:skip放在套件test_suite()上,這樣bazel2gn就不會在BUILD.gn中產生group("tests")或group("host_tests")目標。清除已刪除 GN 測試目標的參照。移除 GN 測試目標後 (請參閱「在兩個建構系統中測試程式庫」),請從列出該目標的 GN 測試群組中刪除。請勿將實際建構或封裝測試的依附元件替換為
bazel_test_suite():bazel_test_suite()只會發出tests.json的中繼資料,不會自行建構任何內容。在 GN 中保留 E2E 測試。目前無法在 Bazel 中定義 E2E 測試 (需要裝置和產品組合的主機測試) (fxbug.dev/576736818)。
在兩個建構系統中測試程式庫
如果程式庫由兩個建構系統中的目標使用,請在兩個建構系統中執行測試。當程式庫的使用者只使用 Bazel 時,請只在 Bazel 中執行測試。如果目標僅在 Bazel 中建構,例如遷移的主機工具、沒有剩餘 GN 使用者的程式庫,以及未將程式庫匯出至 GN 的分葉整合測試套件,則測試只會在 Bazel 中執行。
遷移至 Bazel 的程式庫會保留在 GN 中定義 (通常由 bazel2gn 產生),直到沒有 GN 目標依附於該程式庫為止。在此期間,程式庫的 GN 和 Bazel 建構作業可能會有差異,只有測試才能發現。編譯器旗標、建構變化版本 (例如清理工具) 和僅限 GN 的 bazel2gn 覆寫,在兩個建構系統之間都有所不同。部分屬性也會在翻譯期間遭到捨棄,而 GN 目標是未遷移的依附元件實際連結的目標。在兩個建構系統中執行每項測試,會耗費額外的建構時間和測試容量,但只有在程式庫同時有兩個建構系統的使用者時,才會發生這種情況。
實際應用:
在 Bazel 中定義測試,並讓
bazel2gn產生 GN 副本。遷移BUILD.gn由bazel2gn產生的程式庫時,請一併遷移測試,且不要在測試中加入# @bazel2gn:skip。bazel2gn會將fx_cc_test_binary()、rustc_test()、go_test()、host_rustc_test()、host_go_test()、fx_unittest_package()、fx_package()目標轉譯為test_components(包含其fx_test_component()和fx_test()),以及 Rust 規則的with_unit_tests、with_host_unit_tests和test_deps屬性。按照上述方式,將 Bazel 測試掛接到 GN 測試圖,並在列出原始 GN 測試的 GN 測試群組中,列出產生的 GN 副本。裝置測試套件在 GN 中有不同的名稱。GN 測試套件和 Bazel 副本會發布至同一個 Package Repository,因此不能共用套件名稱。
bazel2gn會將-gn附加至fx_unittest_package()或測試fx_package()的 GN 副本套件名稱,而 Bazel 測試會保留原始名稱,因此遷移時測試網址不會變更。如果
bazel2gn還無法翻譯測試的套件,而您想繼續在 GN 中執行測試,請使用bazel2gn翻譯測試二進位檔,並在BUILD.gn中## BAZEL2GN SENTINEL的上方,使用package_name = "<name>-gn"手動編寫 GN 測試套件。這適用於使用fx_unittest_package(resources = [...])的裝置測試,或具有bazel2gn不支援屬性的測試fx_package()(將# @bazel2gn:skip放在套件和fuchsia_package_resource_group()上,而非測試二進位檔)。C++ 主機測試需要手寫 GN
host_test()。bazel2gn會將fx_cc_test_binary()轉譯為 GNcc_test_executable(),這只會建構二進位檔,不會轉譯host_cc_test()或host_test()。如要在 GN 中繼續執行 C++ 主機測試,請編寫 GNhost_test(),在BUILD.gn的if (is_host)內執行## BAZEL2GN SENTINEL上方產生的二進位檔,並使用($host_toolchain)將其列在 GN 測試群組中。何時應使用
# @bazel2gn:skip選擇不採用。根據預設,如果bazel2gn可以自動轉譯程式庫的測試,請繼續在兩個建構系統中執行這些測試。您可以在測試目標或測試屬性上放置# @bazel2gn:skip(並附上簡短註解說明原因),且僅在下列情況下於 Bazel 中執行:- 受測目標僅在 Bazel 中建構 (例如,在本身具有
# @bazel2gn:skip的同一個BUILD.bazel檔案中的二進位檔或程式庫)。 bazel2gn不支援測試的規則或屬性 (例如cc_test()、host_cc_test()、host_py_test()、host_shac_test()、host_test()、具有data/test_data/test_label的主機測試、具有resources的fx_unittest_package(),或具有跨套件srcs/crate或衝突rustc_env的rustc_test()),且在哨兵上方維護手寫 GN 測試目標不值得額外的複雜性。- 在兩個建構系統中執行或維護測試的成本,高於僅限 GN 迴歸的風險。請根據下列條件評估取捨:
- 目標同位:程式庫的
BUILD.bazel是否在依附元件、設定或編譯器旗標上使用# @bazel2gn:raw_overwrite、# @bazel2gn:path_overwrite或# @bazel2gn:skip,或者是否為在 GN 中跨多個設定編譯的 IDK/SDK 程式庫?如果產生的 GN 目標與 Bazel 目標為 1:1 轉譯,則 Bazel 測試已執行相同的程式碼。 - 未遷移的 GN 依附元件:程式庫是否依附於經常變更的 GN 專屬目標?預先提交受影響測試分析不會從 GN 目標追蹤到 Bazel 測試,因此變更僅限 GN 的依附元件不會在預先提交中觸發僅限 Bazel 的測試。
- 測試權重:快速、獨立的單元測試很容易鏡像;緩慢或耗用大量資源的整合測試 (或其餘 GN 使用者正在積極遷移的程式庫) 適合僅在 Bazel 中執行。
- 受測目標僅在 Bazel 中建構 (例如,在本身具有
如果 Bazel 還無法表示測試,請將測試保留在
## BAZEL2GN SENTINEL上方的 GN 中,並在註解中說明原因。例如端對端測試、需要 Ninja 生成輸入內容的測試、bootfs_test(),以及跨多個 C++ 標準編譯的sdk_cpp_unittest_package()。移除 GN 副本和程式庫。當程式庫的最後一位 GN 使用者遷移至 Bazel 時,請刪除程式庫的 GN 定義及其測試,並從列出 GN 測試的 GN 測試群組中移除 GN 測試。
執行 Fuchsia Bazel 裝置測試
匯出後,請按照 GN 測試的方式,透過套件網址或套件名稱執行 Bazel 裝置測試:
fx test fuchsia-pkg://fuchsia.com/bar_tests#meta/bar_test.cmfx test 會直接叫用 Bazel (做為 fx build --fuchsia_platform bazel_label) 來建構測試,然後在執行測試前發布 bazel_test_packages.list 中列出的套件資訊清單。與 GN 裝置測試一樣,您必須執行套件伺服器,並連結裝置或模擬器。
執行 Fuchsia Bazel 主機測試
本機測試
使用 fx test 執行測試
如要使用 fx test 執行 Bazel 主機測試,請務必按照上述「將 Bazel 主機測試匯出至 fx test 和基礎架構建構工具」一節中的操作說明匯出測試。
匯出測試後,請使用 fx test --host <name_or_label> 在本機建構及執行 Bazel 主機測試,方法與 GN 定義的主機測試相同。
唯一的差別在於,測試會直接叫用 Bazel,完全略過 Ninja,視需要建構。
使用 fx test 時,請注意下列事項:
<name_or_label>將進行模糊比對,如果情況不明確,fx test會回報多個候選地點。<name_or_label>無法參照 Bazeltest_suite()標籤,就像無法參照 GNgroup()標籤一樣。
如要進一步瞭解如何使用 fx test,請參閱 fx 測試的使用手冊。
直接使用 fx bazel test 執行測試
您可以使用 fx bazel test --config=host <target_pattern>,直接透過 Bazel 在本機建構及執行測試。這不需要額外的管道,就能讓 fx test 看到測試 (如上一節所述),並具有下列優點:
<target_pattern>是一組 Bazel 目標模式,可比對「指定套件中的所有測試目標」,在這種情況下,Bazel 會自動略過非測試目標。<target_pattern>可比對test_suite()標籤,方便在開發期間重複執行一組主機測試。bazel test會快取測試結果,且只會重新執行自上次叫用後,受最新變更影響的測試。(使用
--nocache_test_results旗標即可停用這項功能)。<target_pattern>可以參照tests.json中未顯示的標籤。 在開發期間新增測試時,這項功能非常實用。
基礎架構測試
只有 tests.json 中列出的主機測試,才能在基礎架構測試機器人上啟動。這項規定同樣適用於 GN 和 Bazel 主機測試。因此,您必須按照上述「將 Bazel 主機測試匯出至 fx test 和基礎架構建構工具」一節,確保這些測試會顯示在 tests.json 中,否則系統不會在基礎架構上持續測試。
Infra 會使用 fint 建構 Bazel 測試,該指令會在執行 ninja 後直接呼叫 bazel build,建構 bazel_test_suite GN 目標中列出的所有 Bazel 測試。
在基礎架構測試執行器上執行 GN 和 Bazel 定義的主機測試,或收集結果時,兩者之間沒有明確區別。具體來說,基礎架構不會使用 bazel test 執行測試。而是直接執行 bazel build 產生的二進位檔,就像執行 ninja 的主機測試一樣。
偵錯符號傳播
使用偵錯符號編譯的主機測試二進位檔必須註冊未去除的 ELF 二進位檔,工具才能符號化回溯追蹤,並關聯 LLVM 程式碼涵蓋率設定檔 (-profile-correlate=binary)。
如需 Fuchsia 如何管理 Bazel 偵錯符號的一般背景資訊,請參閱「偵錯符號產生技術附註」。
使用偵錯符號編寫主機測試規則
一般 host_test() 規則會在 FuchsiaHostTestInfo 供應器中公開 unstripped_binary 欄位:
如果未明確設定
unstripped_binary,host_test()會檢查基礎binary屬性:- 如果
binary提供DebugPackageInfo(C++ 目標),則會使用DebugPackageInfo.unstripped_file。 - 如果
binary提供CrateInfo(Rust 目標),則會使用CrateInfo.output。
- 如果
如果測試使用包裝函式指令碼啟動器 (例如
host_rustc_test()中的rust_test_parser),巨集「必須」透過unstripped_binary明確轉送原始未去除的二進位目標:host_test( name = name, binary = wrapper_script, unstripped_binary = ":" + binary_name, ... )
傳播至基礎架構和 debuginfod
將 Bazel 主機測試匯出至 GN 建構作業時:
測試查詢:
bazel_tests_utils.py使用//build/bazel/starlark/FuchsiaHostTestInfo.cquery執行bazel cquery,為所有已註冊的主機測試擷取unstripped_binary的 execroot 路徑。主機測試資訊清單:路徑會根據 Ninja 建構目錄進行正規化,並寫入
${root_build_dir}/bazel_host_tests.debug_symbols.json。GN 建構 API 整合:
BUILD.gn中的//:bazel_host_test_suites會附加指向bazel_host_tests.debug_symbols.json的debug_symbol_manifests中繼資料,由build_api_module("debug_symbols")目標使用。Artifactory 上傳:在 CI/CQ 建構作業中,Artifactory 會處理
debug_symbols.json,並將未去除的 ELF 二進位檔上傳至雲端儲存空間/debuginfod 伺服器,讓covargs等工具解析建構 ID。
本機開發和fx coverage
在本機執行涵蓋率時,未提交的二進位檔會產生新的建構 ID,而這些 ID 不會出現在 debuginfod 伺服器上。
為支援本機符號關聯,fx coverage 會執行:
python3 ${FUCHSIA_DIR}/build/bazel/scripts/copy_bazel_debug_symbols.py ${FUCHSIA_BUILD_DIR}
這個指令碼會讀取 bazel_host_tests.debug_symbols.json、計算每個 ELF 二進位檔的 GNU Build ID,並將未去除的二進位檔複製或符號連結至 ${root_build_dir}/.build-id/xx/yyyyyyyy.debug。ffx coverage 和 llvm-profdata 等工具會透過 .symbol-index.json 解析這些二進位檔。
常見問題
Bazel 測試相容性
如果 test_suite() (或其任何依附元件) 中的任何測試與目前設定不相容 (例如使用 target_compatible_with),系統會在評估套件時略過該測試,而不會導致建構失敗。
在指令列使用 //... 和 :all 等模式時,也適用同樣的做法。
詳情請參閱不相容目標的處理方式。
執行 test_suite() 或使用目標模式時,開發人員必須確認相關測試回報為 PASSED (而非 SKIPPED)。