測試 FIDL 通訊協定

必要條件

本教學課程以 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 編寫。

設定依附元件

如要設定依附元件:

  1. 納入測試所需的程式庫:

    #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"
    
  2. 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" ]
    }
    
    

建立伺服器實作

如何建立伺服器實作:

  1. 新增所測試 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_ 方法,系統就會在呼叫未覆寫的任何要求處理常式方法時呼叫此方法。

  2. 建立測試類別,納入發布 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() 方法,可在 Proxy 上初始化目前的測試元件內容並傳回。

新增測試

您可以使用測試固件編寫的測試範例:

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);
}

執行測試

如何執行測試:

  1. 設定 GN 版本以納入測試:

    fx set core.x64 --with //examples/fidl/hlcpp/testing
    
  2. 執行測試:

    fx test -vo example-hlcpp-protocol-test
    

您應該會看到顯示成功的測試輸出內容。

摘要

  • gtest::TestLoopFixture 可省去樣板非同步迴圈設定程式碼的需求。每個測試案例只需呼叫 RunLoopUntilIdle() 即可,無需手動管理 async::Loop
  • ComponentContextProvider 可讓您在測試期間輕鬆模擬元件結構定義。舉例來說,這適合用來為元件提供特定功能。
  • HLCPP 繫結測試鷹架會為每個通訊協定類別提供測試基礎,每個類別均具有每個方法的預留位置實作。如此一來,測試就只能實作受測方法。