RFC-0180:測試 UI 堆疊

RFC-0180:測試 UI 堆疊
狀態已接受
區域
  • 查看系統
說明

這項 RFC 是針對 Test UI Stack 元件的設計提案,可提供 UI 專屬測試功能,用於測試樹狀結構內外的用戶端。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-06-16
審查日期 (年-月-日)2022-07-26

摘要

這個 RFC 是針對測試 UI 堆疊元件提出的設計建議,將提供特定 UI 的測試功能,用於測試樹狀結構內外的用戶端。

提振精神

整合測試對於 Fuchsia 花瓣的穩定性至關重要。不過,目前很少有樹狀結構外 (「OOT」) 的密封式 UI 整合測試,因為 OOT 用戶端在編寫這些測試時會遇到重大障礙。具體來說,他們必須:

  • 瞭解 UI 堆疊的專業知識,通常超出實際用途的範圍。
  • 將測試行為與 UI 堆疊的內部實作詳細資料配對。
  • 使用僅限內部使用的 FIDL API 執行相關 UI 元件。
  • 設計測試,以便在 UI 堆疊 (GFX -> flatland、root presenter -> scene manager、CFv1 -> CFv2) 中,對各種進行中的遷移作業保持彈性。

測試 UI 堆疊元件旨在代表測試用戶端處理低層級 UI 詳細資料,以減輕這些問題。

應用實例

  • 用戶端執行階段的觸控/滑鼠/鍵盤輸入測試:針對這些測試,用戶端會顯示 Test UI 堆疊、將檢視畫面附加至場景、等待檢視區塊狀態靜止、插入輸入內容,並觀察其檢視畫面如何處理傳入的事件。
  • 應用程式測試:這些測試可針對 UI 堆疊執行應用程式的部分內容,並觀察其如何轉譯內容、處理輸入內容、與無障礙功能互動等。
  • 與 UI 相關的測試:某些未明確執行 UI 功能的測試可能仍需要 UI 的存在。舉例來說,fuchsia.web 的測試可能需要測試用戶端呈現檢視畫面。

相關人員

誰會受到這項 RFC 是否通過的影響?(此為選用部分,但建議您填寫)。

協助人員:

leannogasawara@google.com

審查者:

  • Fuchsia 測試架構:crjohns@google.com
  • UI + OOT 整合測試:dworsham@google.com、jaeheon@google.com

諮詢:

列出應審查 RFC 但不需要核准的人員。

  • 輸入:quiche@google.com、neelsa@google.com
  • 無障礙功能:neelsa@google.com、lucasradaelli@google.com
  • 元件架構:yaneury@google.com、geb@google.com、cgonyeo@google.com
  • Flutter:akbiggs@google.com
  • Chromium:sergeyu@google.com
  • Opal:cligh@google.com、anwilson@google.com、robinsontom@google.com

社會化:

這項 RFC 已通過 Fuchsia 測試和 Fuchsia 輸入團隊的設計審查。我們也諮詢了 OOT UI 客戶團隊。

詞彙解釋

  • UI 堆疊:提供必要 UI 服務的 Fuchsia 元件組合。大致來說,這個集合包含 scenic、根呈現工具或場景管理工具、輸入管道、無障礙功能管理工具、捷徑管理工具和文字管理工具。
  • 測試 UI 堆疊:建議的元件,可公開 UI 堆疊 (基本 UI 服務 + 輔助服務) 的外觀。
  • 基本 UI 服務:從正式版 UI 領域公開的服務組合。
  • 輔助服務:僅供測試的服務,可透過較高層級的 API 將低層級 UI 功能代理至用戶端。
  • SceneView的階層,可讓擁有者向螢幕呈現可算繪的內容、使用輸入內容,以及與無障礙功能互動。

設計

需求條件

  • 涉及使用者介面的密封 OOT 整合測試必須容易編寫。
  • 涉及 UI 的密封 OOT 整合測試必須可讀。
  • 測試操作元素不得洩漏 UI 堆疊的內部資訊。
  • 用戶端必須能夠設定包含 UI 堆疊的測試領域。
  • 用戶端必須能夠擴充 Test UI Stack 定義的元件拓撲,以納入測試專屬設定。
  • 測試必須保證能乾淨俐落地設定和拆除。
  • 測試必須彼此隔離。
  • 測試 UI 堆疊不得禁止使用 RealmBuilder。
  • 用戶端必須能夠以所選語言編寫測試。

建議使用

  • 樹狀結構內和樹狀結構外的 UI 整合測試應直接類似。

總覽

我們建議將 Test UI Stack 元件新增至 Fuchsia 合作夥伴 SDK,以便公開正式版 UI 領域的門面。具體來說,這個元件會公開下列服務:

  1. 大致上,是從實際執行環境 UI 領域公開的一組公用服務。
  2. 一組僅供測試的「輔助服務」,可透過高階抽象 (例如輸入合成、螢幕截圖等) 提供低階 UI 功能。

用戶端可以將此元件例項化,將必要的 UI 服務轉送至測試中的元件,在場景中顯示檢視畫面,並使用提供的各種輔助服務來執行測試。

替代文字:顯示的元件拓樸:
測試管理器 -> 測試測試板元件
測試板元件 -> 測試 UI 堆疊元件
測試板元件 -> 測試 UI 用戶端
測試板元件 -> 支援元件
測試板元件 -> 本機模擬資料
測試 UI 堆疊元件 -> 輔助元件
測試 UI 堆疊元件 -> 基本 UI 元件服務路徑
輔助元件 -> 測試 UI 堆疊元件 (輔助服務)
基本 UI 元件 -> 測試 UI 堆疊元件 (基本 UI 服務)
測試 UI 堆疊元件 -> 測試板元件 (基本 UI 服務、輔助服務)
測試 UI 堆疊元件 -> 測試 UI 用戶端 (基本 UI 服務)
測試 UI 用戶端 -> 測試板元件 (fuchisa.ui.app.ViewProvider)
支援元件 -> 測試 UI 用戶端 (支援服務)
本機模擬資料 -> 測試 UI 用戶端 (模擬服務)

請注意,此設計與 UI 堆疊和測試元件如何設定各自的領域無關。可透過靜態方式或 RealmBuilder 進行。

基礎 UI 拓撲

一開始,測試 UI 堆疊會包含下列基礎 UI 元件,這些元件會反映撰寫時的「現代」實際作業 UI 堆疊:

  1. 風景優美,已設定為使用平地。
  2. 場景管理員
  3. Accessibility Manager
  4. 文字管理工具
  5. 捷徑管理員
  6. Cobalt (並非 UI 元件,但必須執行 scenic)
  7. 假的硬體顯示控制器 (再次強調,這不是 UI 元件,但 scenic 需要)

此外,Test UI 堆疊會在初始階段將下列基本 UI 服務公開給測試:

  1. fuchsia.accessibility.semantics.SemanticsManager
  2. fuchsia.ui.composition.Allocator
  3. fuchsia.ui.composition.Flatland
  4. fuchsia.ui.scenic.Scenic
  5. fuchsia.ui.input.ImeService
  6. fuchsia.ui.input3.Keyboard
  7. fuchsia.ui.input3.KeyEventInjector
  8. fuchsia.ui.shortcut.Manager
  9. fuchsia.ui.shortcut.Registry

請注意,測試 UI 堆疊可以且將會進化,以便與實際環境中的 UI 保持一致。

One UI 堆疊遷移的進度而定,我們也可能會新增「舊版」的測試 UI 堆疊元件,以便使用根呈現工具和輸入管道取代場景管理工具。

輔助元件

除了上述提到的基本 UI 元件,Test UI Stack 還會納入一組範圍較窄的輔助元件,透過較高層級的 API 為用戶端提供低階 UI 專屬功能。在推出時,這組合可能包含:

  1. 輸入合成元件,可讓用戶端將文字、滑鼠和觸控輸入內容直接注入輸入管道。
  2. 螢幕截圖元件,可讓使用者以符合人體工學的方式擷取螢幕畫面。
  3. 場景供應器元件,用於將用戶端檢視畫面附加至場景,並代為註冊特權操作功能 (例如範圍限定的幾何圖形觀察器)。請注意,由於場景供應器會代表用戶端註冊觀察器,因此測試 UI 堆疊「不需要」公開任何觀察器註冊服務。

測試 UI 堆疊會公開這些元件的輔助服務,供用戶端用於執行測試。

輔助元件抽象化可提供以下幾項重要好處:

  • 抽象:輔助服務會向用戶端提供穩定且明確定義的介面,有助於盡量減少對 UI 堆疊內部依附元件的依附性。
  • 簡單:透過專屬的輔助元件提供 UI 功能,可讓每個 FIDL API 保持簡單且具體,進而改善撰寫及維護 UI 測試的 DX。
  • 可擴充性:我們可以新增新的輔助元件,輕鬆擴充 UI 外觀。
  • 與子套件的相容性:我們可以轉換至子套件,而不會讓用戶端失去功能。

可設定性

部分用戶端可能需要設定參數,例如螢幕旋轉、像素密度等。Test UI Stack 可透過結構化元件設定支援這些用途。用戶端可以覆寫要控制的參數,然後 Test UI Stack 元件可將這些參數傳播至適當的基本 UI 元件。

使用範例

下方的偽 C++ 程式碼片段概述了使用 Test UI Stack 元件的觸控輸入測試。

// Client test code creates a RealmBuilder instance.
component_testing::RealmBuilder realm_builder;

// Instantiate Test UI Stack component by absolute URL in the test realm.
realm_builder.AddChild("test-ui-stack",
            "fuchsia-pkg://fuchsia.com/test-ui-stack#meta/test-ui-stack.cm");

// Add a test view component to the test realm, and route required UI services
// to it.
realm_builder.AddChild("test-view", ...);
realm_builder.AddRoute({
    .capabilities = {Protocol{fuchsia::ui::scenic::Scenic::Name_}},
    .source = ChildRef{"test-ui-stack"},
    .targets = {"test-view"}},
}});

// Expose fuchsia.ui.app.ViewProvider from the test view.
realm_builder.AddRoute({
    .capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
    .source = ChildRef{"test-view"},
    .targets = {ParentRef()}},
}});

// Build the test realm.
RealmRoot realm_root = realm_builder_.Build();

// Connect to the scene provider "helper service", and request to attach a
// test view to the scene.
std::optional<zx_koid_t> client_view_ref_koid;
fuchsia::ui::observation::geometry::Provider geometry_provider;
auto scene_provider = realm_root->Connect<fuchsia::ui::test::scene::Provider>();
auto view_provider = realm_root_->Connect<fuchsia::ui::app::ViewProvider>();
scene_provider->AttachView(std::move(view_provider), geometry_provider.NewRequest(),
  [&client_view_ref_koid](auto view_ref_koid) {
    // Save the client's ViewRef koid.
    client_view_ref_koid = view_ref_koid;
  });

// Wait for client view ref koid to become available.
RunLoopUntil([&client_view_ref_koid] {
  return client_view_ref_koid.has_value();
});

// Use registered geometry provider to wait for client view to render.
ASSERT_TRUE(geometry_provider.is_bound());
geometry_provider.Watch(...);
RunLoopUntil(...);

// Connect to input synthesis helper service, and use to inject input.
auto input_synthesis = realm_root->Connect<fuchsia::ui::test::input::Touch>();
input_synthesis->InjectTap(...);

實作

下列列舉的工作流程可同時進行。

工作流程:場景供應器輔助服務

  1. 發布 FIDL 變更。
  2. 實作場景提供者輔助元件。
  3. 重構現有的樹狀結構內測試,以便使用場景供應器。

這個工作流程可讓測試將檢視畫面附加至場景,這是任何圖形/輸入測試的硬性需求。

工作流程:幾何圖形觀察器

  1. 在 SDK 中提供 fuchsia.ui.observation.geometry 通訊協定。
  2. 實作「已劃分範圍」的幾何圖形觀察器註冊項目。

這個工作流程可讓 OOT 用戶端使用幾何觀察器資料,不受場景圖表根節點影響,而這可能會因不同產品和 UI 堆疊設定而異。

工作流程:輸入合成

  1. 重新設計輸入合成 API,以便在 OOT 中使用。
  2. 將輸入合成 FIDL 程式庫新增至 SDK。
  3. 實作 FIDL 程式庫。

這個工作串流可讓 OOT 測試 UI 堆疊使用者插入輸入內容,目前沒有其他替代方案。

工作流程:重構樹狀結構內 UITestManager 程式庫

  1. 將現有內部 UITestManager 類別的領域設定因素,轉移至可與 Test UI 堆疊共用的新 UITestRealm 類別。
  2. (選用) 實作機制,以便將 .cml 與正式版 UI 子領域共用。如果不是現在,我們應該在 One UI 堆疊遷移完成後進行清除。

完成上述工作流程後,我們就能在合作夥伴 SDK 中組合 Test UI Stack 套件,並將其新增至 OOT 用戶端執行測試的產品版本。

成效

這項設計針對的是已是多元件整合測試,因此我們預期測試拓樸的擴充功能會對效能造成最少的影響。

部分 OOT 測試可依靠更穩定的同步處理模式,因此實際上效能可能會有所提升。

安全性考量

此 RFC 沒有任何安全性考量。由於測試 UI 堆疊不會使用任何系統功能 (除了 sysmem 和 vulkan),因此無法執行一般使用者 vulkan 程式無法執行的任何操作。

隱私權注意事項

測試 UI 堆疊無法存取私人或機密資源,因此此 RFC 沒有隱私權考量。

測試

我們可以編寫測試來使用 Test UI Stack,進而對其行為有充分信心。

說明文件

我們打算發布開發人員指南,說明如何使用 Test UI Stack。

缺點、替代方案和未知事項

缺點

在不同用戶端中重複使用樣板

建議的設計讓用戶端可以編寫一些常見的模板。我們可以透過 fuchsia.test.Suite 的自訂 UI 實作項目來解決這個問題,讓客戶將測試用戶端和測試邏輯插入預先定義的 UI 測試架構。

考慮的替代方案

請參閱原始的 UI Test Manager RFC