前提条件
本教程以 HLCPP 使用入门教程为基础。
概览
本教程介绍了如何为 Echo.EchoString
方法编写测试。本教程将向您介绍如何使用两个实用程序来测试在 HLCPP 中实现的 FIDL 协议:
gtest
测试循环夹具sys::testing::ComponentContextProvider
。- HLCPP 绑定提供的
fidl_test_base.h
文件
如果您要自行编写代码,请删除以下目录:
rm -r examples/fidl/hlcpp/testing/*
该测试将以 examples/fidl/hlcpp/testing/main.cc
编写。
设置依赖项
如需设置依赖项,请执行以下操作:
添加测试所需的库:
#include <fuchsia/examples/cpp/fidl.h> #include <fuchsia/examples/cpp/fidl_test_base.h> #include <lib/fidl/cpp/binding.h> #include <lib/sys/cpp/testing/component_context_provider.h> #include "src/lib/testing/loop_fixture/test_loop_fixture.h"
在
examples/fidl/hlcpp/testing/BUILD.gn
中为测试添加构建规则:# Copyright 2020 The Fuchsia Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/components.gni") executable("bin") { testonly = true output_name = "example_hlcpp_protocol_test" sources = [ "main.cc" ] deps = [ "//examples/fidl/fuchsia.examples:fuchsia.examples_hlcpp", "//sdk/lib/fidl/cpp", "//sdk/lib/sys/cpp", "//sdk/lib/sys/cpp/testing:unit", "//src/lib/fxl/test:gtest_main", "//src/lib/testing/loop_fixture", ] } fuchsia_unittest_package("example-hlcpp-protocol-test") { deps = [ ":bin" ] } group("hermetic_tests") { testonly = true deps = [ ":example-hlcpp-protocol-test" ] }
创建服务器实现
如需创建服务器实现,请执行以下操作:
为经过测试的
Echo
协议添加实现:class EchoImpl : public fuchsia::examples::testing::Echo_TestBase { public: void EchoString(std::string value, EchoStringCallback callback) override { callback(value); } void NotImplemented_(const std::string& name) override { std::cout << "Not implemented: " << name << std::endl; } };
此实现从相应的测试基类继承,而不是从
fuchsia::examples::Echo
继承。这意味着,实现只需替换要测试的方法(在本例中为EchoString
)以及NotImplemented_
方法(在调用任何未替换的请求处理程序方法时,就会调用该方法)。创建一个测试类,用于封装发布 echo 协议的逻辑:
class EchoServerInstance { public: explicit EchoServerInstance(std::unique_ptr<sys::ComponentContext> context) { context_ = std::move(context); binding_ = std::make_unique<fidl::Binding<fuchsia::examples::Echo>>(&impl_); fidl::InterfaceRequestHandler<fuchsia::examples::Echo> handler = [&](fidl::InterfaceRequest<fuchsia::examples::Echo> request) { binding_->Bind(std::move(request)); }; context_->outgoing()->AddPublicService(std::move(handler)); } private: EchoImpl impl_; std::unique_ptr<fidl::Binding<fuchsia::examples::Echo>> binding_; std::unique_ptr<sys::ComponentContext> context_; };
这类似于服务器教程中介绍的代码,但
fidl::Binding
归类所有。这会在类被销毁时调用绑定的析构函数。这样一来,代码就可以在有新的测试组件上下文实例的情况下,在每个测试用例上发布 echo 协议。
实现测试固件类
class EchoTestFixture : public gtest::TestLoopFixture {
public:
void SetUp() override {
TestLoopFixture::SetUp();
echo_instance_.reset(new EchoServerInstance(provider_.TakeContext()));
}
void TearDown() override {
TestLoopFixture::TearDown();
echo_instance_.reset();
}
protected:
fuchsia::examples::EchoPtr GetProxy() {
fuchsia::examples::EchoPtr echo;
provider_.ConnectToPublicService(echo.NewRequest());
return echo;
}
private:
std::unique_ptr<EchoServerInstance> echo_instance_;
sys::testing::ComponentContextProvider provider_;
};
测试夹具执行以下操作:
- 保存
ComponentContextProvider
的实例。每个测试都会使用该上下文创建新的测试上下文,并使用EchoServerInstance
类将 Echo 实现绑定到该上下文。 - 提供
GetProxy()
方法,用于初始化当前测试组件上下文的代理并返回。
添加测试
以下是您可以使用测试夹具编写的测试示例:
TEST_F(EchoTestFixture, EchoString) {
fuchsia::examples::EchoPtr proxy = GetProxy();
bool received_response = false;
proxy->EchoString("hello there", [&](std::string response) {
ASSERT_EQ(response, "hello there");
received_response = true;
});
proxy.set_error_handler(
[](zx_status_t status) { ASSERT_TRUE(false && "should not throw any errors"); });
RunLoopUntilIdle();
EXPECT_TRUE(received_response);
}
运行测试
如需运行测试,请执行以下操作:
配置 GN build 以包含测试:
fx set core.x64 --with //examples/fidl/hlcpp/testing
运行测试:
fx test -vo example-hlcpp-protocol-test
您应该会看到指示成功的测试输出。
总结
gtest::TestLoopFixture
无需样板异步循环设置代码。每个测试用例可以直接调用RunLoopUntilIdle()
,而无需手动管理async::Loop
。- 借助
ComponentContextProvider
,您可以在测试期间轻松模拟组件上下文。例如,这对于为组件提供特定功能很有用。 - HLCPP 绑定测试基架会为每个协议类提供一个测试库,其中每个方法都有一个占位实现。这样,测试就可以仅实现被测方法。