集成测试

集成测试侧重于验证组件与系统中的其他组件交互时的行为。因此,集成测试通常与主组件分开构建,并且可能会将受测组件和其他依赖项声明为子组件。根据测试的性质,依赖项组件可能会以模拟或桩的形式提供,以促进测试用例保持封闭状态。

测试组成部分

下面是一个简单集成测试组件的示例组件清单:

Rust

meta/integration_tests.cml:

{
    include: [
        "syslog/client.shard.cml",
        "//src/sys/test_runners/rust/default.shard.cml",
    ],
    program: {
        binary: "bin/client_test",
    },
    children: [
        {
            name: "service",
            url: "fuchsia-pkg://fuchsia.com/foo-package-tests#meta/mock_service.cm",
        },
        {
            name: "client",
            url: "fuchsia-pkg://fuchsia.com/foo-package-tests#meta/foo_client.cm",
        },
    ],
    offer: [
        {
            protocol: "fuchsia.example.Foo",
            from: "#service",
            to: [ "#client" ],
        },
    ],
}

C++

meta/integration_tests.cml:

{
    include: [
        "syslog/client.shard.cml",
        "//src/sys/test_runners/gtest/default.shard.cml",
    ],
    program: {
        binary: "bin/client_test",
    },
    children: [
        {
            name: "service",
            url: "fuchsia-pkg://fuchsia.com/foo-package-tests#meta/mock_service.cm",
        },
        {
            name: "client",
            url: "fuchsia-pkg://fuchsia.com/foo-package-tests#meta/foo_client.cm",
        },
    ],
    offer: [
        {
            protocol: "fuchsia.example.Foo",
            from: "#service",
            to: [ "#client" ],
        },
    ],
}

此测试组件声明包含以下关键元素:

  1. 特定于语言的必要测试运行程序分片的 include。这样,测试管理器就可以正确执行测试套件。
  2. 将被测组件和依赖组件列为 children
  3. 在测试领域的组件之间路由所需的功能。

Fuchsia 构建系统为不同的测试组件(例如集成测试)提供 fuchsia_test_package() GN 目标。利用此规则,您可以将包含测试的组件与所需测试分开声明为依赖项,并描述应在其中运行测试的目标设备环境。

以下示例展示了如何将上述集成测试添加到 BUILD.gn 文件中:

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

// Component under test
fuchsia_component("foo_client") {
  deps = [ ... ]
  manifest = "meta/foo_client.cml"
}

// Test dependencies
fuchsia_component("mock_service") {
  deps = [ ... ]
  manifest = "meta/mock_service.cml"
  testonly = true
}

// Component containing integration tests
fuchsia_component("integration_tests") {
  deps = [ ":bin_test" ]
  manifest = "meta/integration_tests.cml"
  testonly = true
}

fuchsia_test_package("hello-world-tests") {
  test_components = [ ":integration_tests" ]
  deps = [
    ":foo_client",
    ":mock_service",
  ]
}

练习:Echo 服务器集成测试

在本练习中,您将添加一个集成测试组件,以使用测试运行程序框架来练习 echo_server 组件的 FIDL 协议接口,并在 FEMU 环境中运行这些测试。

添加集成测试组件

首先,在 //vendor/fuchsia-codelab 目录中为名为 echo-integration 的新集成测试组件创建项目基架:

mkdir -p vendor/fuchsia-codelab/echo-integration

在新项目目录中创建以下文件和目录结构:

Rust

echo-integration
  |- BUILD.gn
  |- meta
  |   |- echo_integration.cml
  |
  |- src
      |- lib.rs
  • BUILD.gn:测试二进制文件、组件和软件包的 GN 构建目标。
  • meta/echo_integration.cml:声明被测组件及其功能的清单。
  • src/lib.rs:Rust 集成测试的源代码。

C++

echo-integration
  |- BUILD.gn
  |- meta
  |   |- echo_integration.cml
  |
  |- echo_integration_test.cc
  • BUILD.gn:测试二进制文件、组件和软件包的 GN 构建目标。
  • meta/echo_integration.cml:声明被测组件及其功能的清单。
  • echo_integration_test.cc:C++ 集成测试的源代码。

更新测试组件清单

测试组件的清单会应用基准依赖项,例如 test_runners。更新 echo_integration.cml 文件以将 echo-server 组件声明为子组件,并将 Echo 协议功能路由到测试组件。

Rust

echo-integration/meta/echo_integration.cml:

{
    include: [
        "//src/sys/test_runners/rust/default.shard.cml",
        "syslog/client.shard.cml",
    ],

    // Information about the program to run.
    program: {
        // The binary to run for this component.
        binary: "bin/echo_integration_test",
    },


    // Child components orchestrated by the integration test.
    children: [
        {
            name: "echo_server",
            url: "#meta/echo_server.cm",
        },
    ],

    // Capabilities used by this component.
    use: [
        {
            protocol: [ "fidl.examples.routing.echo.Echo" ],
            from: "#echo_server",
        },
    ],

    // Capabilities required by components under test.
    offer: [
        {
            protocol: [
                "fuchsia.inspect.InspectSink",
                "fuchsia.logger.LogSink",
            ],
            from: "parent",
            to: "#echo_server",
        },
    ],
}

C++

echo-integration/meta/echo_integration.cml:

{
    include: [
        "//src/sys/test_runners/gtest/default.shard.cml",
        "syslog/client.shard.cml",
    ],

    // Information about the program to run.
    program: {
        // The binary to run for this component.
        binary: "bin/echo_integration_test",
    },


    // Child components orchestrated by the integration test.
    children: [
        {
            name: "echo_server",
            url: "#meta/echo_server.cm",
        },
    ],

    // Capabilities used by this component.
    use: [
        {
            protocol: [ "fidl.examples.routing.echo.Echo" ],
            from: "#echo_server",
        },
    ],

    // Capabilities required by components under test.
    offer: [
        {
            protocol: [
                "fuchsia.inspect.InspectSink",
                "fuchsia.logger.LogSink",
            ],
            from: "parent",
            to: "#echo_server",
        },
    ],
}

请注意,echo-server 实例来自与集成测试相同的软件包。此做法通过避免依赖于其他软件包的组件,来提升封闭的测试软件包。

实现集成测试

集成测试会连接到 echo-server 公开的 Echo 协议(与客户端组件相同),发送字符串请求,并验证预期响应。

添加以下代码以实现集成测试:

Rust

echo-integration/src/lib.rs:

use {anyhow::Error, fidl_fidl_examples_routing_echo as fecho, fuchsia_component::client};

#[fuchsia::test]
async fn echo_integration_test() -> Result<(), Error> {
    const ECHO_STRING: &str = "Hello, world!";

    let echo = client::connect_to_protocol::<fecho::EchoMarker>()
        .expect("error connecting to echo server");
    let out = echo.echo_string(Some(ECHO_STRING)).await.expect("echo_string failed");

    assert_eq!(ECHO_STRING, out.unwrap());
    Ok(())
}

C++

echo-integration/echo_integration_test.cc:

#include <fidl/examples/routing/echo/cpp/fidl.h>
#include <lib/fidl/cpp/string.h>
#include <lib/sys/cpp/component_context.h>

#include <string>

#include <gtest/gtest.h>

TEST(EchoIntegrationTest, TestEcho) {
  ::fidl::examples::routing::echo::EchoSyncPtr echo_proxy;
  auto context = sys::ComponentContext::Create();
  context->svc()->Connect(echo_proxy.NewRequest());

  ::fidl::StringPtr request("Hello, world!");
  ::fidl::StringPtr response = nullptr;
  ASSERT_TRUE(echo_proxy->EchoString(request, &response) == ZX_OK);
  ASSERT_TRUE(request == response);
}

将以下构建规则添加到 BUILD.gn 文件中,以构建并打包集成测试组件以及 echo 服务器依赖项:

Rust

echo-integration/BUILD.gn:

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


rustc_test("bin") {
  name = "echo-integration-test"
  edition = "2021"

  deps = [
    "//vendor/fuchsia-codelab/echo-fidl:echo_rust",
    "//src/lib/fuchsia",
    "//src/lib/fuchsia-component",
    "//third_party/rust_crates:anyhow",
  ]

  sources = [ "src/lib.rs" ]
}

fuchsia_component("component") {
  testonly = true
  component_name = "echo_integration"
  manifest = "meta/echo_integration.cml"
  deps = [ ":bin" ]
}

fuchsia_test_package("tests") {
  package_name = "echo-integration-tests"
  test_components = [ ":component" ]
  deps =
      [ "//vendor/fuchsia-codelab/echo-server:component" ]
}

C++

echo-integration/BUILD.gn:

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


executable("bin") {
  output_name = "echo-integration-test"
  sources = [ "echo_integration_test.cc" ]
  deps = [
    "//vendor/fuchsia-codelab/echo-fidl:echo_hlcpp",
    "//sdk/lib/sys/cpp",
    "//sdk/lib/sys/cpp/testing:unit",
    "//src/lib/fxl/test:gtest_main",
    "//third_party/googletest:gtest",
    "//zircon/system/ulib/async-loop:async-loop-cpp",
    "//zircon/system/ulib/async-loop:async-loop-default",
  ]
  testonly = true
}

fuchsia_component("component") {
  testonly = true
  component_name = "echo_integration"
  manifest = "meta/echo_integration.cml"
  deps = [ ":bin" ]
}

fuchsia_test_package("tests") {
  package_name = "echo-integration-tests"
  test_components = [ ":component" ]
  deps =
      [ "//vendor/fuchsia-codelab/echo-server:component" ]
}

更新 build 配置

将集成测试软件包添加到 build 配置:

fx set workstation_eng.x64 \
    --with //vendor/fuchsia-codelab/echo-server \
    --with //vendor/fuchsia-codelab/echo-client \
    --with //vendor/fuchsia-codelab/echo-realm \
    --with //vendor/fuchsia-codelab/echo-integration:tests

运行 fx build 并验证构建是否成功完成:

fx build

运行集成测试

fuchsia_test_package() 规则会生成一个包含测试组件及其依赖项的软件包。集成测试组件的网址如下:

fuchsia-pkg://fuchsia.com/echo-integration-tests#meta/echo_integration.cm

使用 ffx test 命令执行集成测试。验证测试是否通过:

ffx test run \
    fuchsia-pkg://fuchsia.com/echo-integration-tests#meta/echo_integration.cm