元件測試

Fuchsia「Test Runner Framework」可讓開發人員使用各種語言和執行階段,為元件建構測試,並在目標裝置上執行。這個架構提供實作 fuchsia.test.Suite 通訊協定的測試執行器元件,並整合常見的語言測試架構,例如 GoogleTest (C++)。

test_manager 元件負責在 Fuchsia 裝置上執行測試。這會檢查實作測試套件通訊協定的元件,並以子項元件的形式啟動這些元件。這表示 test_manager 也會負責為每個測試套件提供功能,建立通常稱為「測試領域」

這張圖表顯示了測試執行器架構如何提供介面,讓開發人員公開測試套件,以及讓開發人員工具在 Fuchsia 裝置上執行測試。

開發人員工具 (例如 ffx test) 會與裝置上的 test_manager 通訊,以便執行測試套件並擷取結果。

測試執行者

在測試執行器架構與開發人員使用的常見架構之間,測試執行器是可重複使用的轉接程式,方便開發人員以偏好的語言編寫測試。每個測試執行元件元件都會公開 fuchsia.test.Suite 能力,讓 test_manager 列舉並執行個別測試,並以測試架構支援宣告適當的執行 runner

Rust

{
    // Execute tests using language-specific runner
    program: { runner: "rust_test_runner" },
    // Expose test suite protocol to test manager
    capabilities: [
        { protocol: "fuchsia.test.Suite" },
    ],
    expose: [
        {
            protocol: "fuchsia.test.Suite",
            from: "self",
        },
    ],
}

C++

{
    // Execute tests using language-specific runner
    program: { runner: "gtest_runner" },
    // Expose test suite protocol to test manager
    capabilities: [
        { protocol: "fuchsia.test.Suite" },
    ],
    expose: [
        {
            protocol: "fuchsia.test.Suite",
            from: "self",
        },
    ],
}

為簡化整合程序,測試執行器架構會為每個語言專屬的執行元件提供資訊清單資料分割。以下為宣告執行工具 CML 的對等測試執行元件 CML,用於宣告先前範例元件測試中的功能。

Rust

{
    include: [ "//src/sys/test_runners/rust/default.shard.cml" ]
}

C++

{
    include: [ "//src/sys/test_runners/gtest/default.shard.cml" ]
}

單元測試

單元測試著重於驗證元件中的個別程式碼單元,並與系統中的其他元件隔離。單元測試應密封,即不需要測試以外的額外功能或提供額外功能。

Fuchsia 建構系統提供額外的 GN 目標,以便進行單元測試元件:

  • fuchsia_unittest_package():單一元件套件,可自動產生最低的元件資訊清單來參照測試二進位檔,且不需要任何額外功能。
  • fuchsia_unittest_component():可產生相同最小元件資訊清單的元件宣告。如果您需要在同一個 fuchsia_package() 中建構多個單元測試元件,這項規則就非常實用。

以下是內含單元測試的 BUILD.gn 程式碼片段範例:

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

executable("bin_test") {
  sources = [ "main_test.cc" ]
  deps = [
    "//src/lib/fxl/test:gtest_main",
    "//third_party/googletest:gtest",
  ]
  testonly = true
}

fuchsia_unittest_package("hello-world-unittests") {
  deps = [
    ":bin_test",
  ]
}

練習:回音單元測試

在本練習中,您要使用測試執行器架構,在 echo-args 元件中新增單元測試,並在 FEMU 環境中執行這些測試。

實作單元測試

單元測試會驗證元件內部函式的行為是否符合預期。針對 echo-args 元件,您需要驗證先前運動中使用的 greeting() 函式是否傳回預期值。

請新增下列單元測試函式,驗證 greeting() 函式透過一、兩個或三個引數提供時的行為:

Rust

echo-args/src/main.rs

#[cfg(test)]
mod tests {
    #[fuchsia::test]
    async fn test_greet_one() {
        let names = vec![String::from("Alice")];
        let expected = "Alice";
        assert_eq!(super::greeting(&names), expected);
    }

    #[fuchsia::test]
    async fn test_greet_two() {
        let names = vec![String::from("Alice"), String::from("Bob")];
        let expected = "Alice and Bob";
        assert_eq!(super::greeting(&names), expected);
    }

    #[fuchsia::test]
    async fn test_greet_three() {
        let names = vec![String::from("Alice"), String::from("Bob"), String::from("Spot")];
        let expected = "Alice, Bob, Spot";
        assert_eq!(super::greeting(&names), expected);
    }
}

C++

echo-args/echo_unittest.cc

#include <gtest/gtest.h>

#include "vendor/fuchsia-codelab/echo-args/echo_component.h"

TEST(EchoTest, TestGreetOne) {
  std::vector<std::string> names = {"Alice"};
  std::string expected = "Alice";
  ASSERT_TRUE(echo::greeting(names) == expected);
}

TEST(EchoTest, TestGreetTwo) {
  std::vector<std::string> names = {"Alice", "Bob"};
  std::string expected = "Alice and Bob";
  ASSERT_TRUE(echo::greeting(names) == expected);
}

TEST(EchoTest, TestGreetThree) {
  std::vector<std::string> names = {"Alice", "Bob", "Spot"};
  std::string expected = "Alice, Bob, Spot";
  ASSERT_TRUE(echo::greeting(names) == expected);
}

更新建構設定

BUILD.gn 檔案中加入下列規則,產生新的單元測試套件:

Rust

echo-args/BUILD.gn

group("tests") {
  testonly = true
  deps = [ ":echo-args-unittests" ]
}

fuchsia_unittest_package("echo-args-unittests") {
  deps = [ ":bin_test" ]
}

C++

echo-args/BUILD.gn

group("tests") {
  testonly = true
  deps = [ ":echo-args-unittests" ]
}

executable("unittests") {
  output_name = "echo-args-test"
  testonly = true

  sources = [ "echo_unittest.cc" ]

  deps = [
    ":cpp-lib",
    "//src/lib/fxl/test:gtest_main",
    "//third_party/googletest:gtest",
  ]
}

fuchsia_unittest_package("echo-args-unittests") {
  deps = [ ":unittests" ]
}

這項規則會將單元測試封裝成具有下列網址的元件:

fuchsia-pkg://fuchsia.com/echo-args-unittests#meta/echo-args-unittests.cm

執行單元測試

更新頂層建構目標,以便同時建構元件套件和測試套件:

Rust

echo-args/BUILD.gn

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


group("echo-args") {
  testonly = true
  deps = [
    ":package",
    ":tests",
  ]
}

C++

echo-args/BUILD.gn

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


group("echo-args") {
  testonly = true
  deps = [
    ":package",
    ":tests",
  ]
}

再次執行 fx build 以建構測試套件:

fx build

使用 ffx test 指令,在此套件中執行單元測試。驗證測試是否通過:

ffx test run \
    fuchsia-pkg://fuchsia.com/echo-args-unittests#meta/echo-args-unittests.cm