
如何實際測試 UI
領先工程團隊使用的測試技術

測試 UI 很麻煩。使用者期望頻繁發布充滿功能的版本。但每個新功能都會引入更多 UI 和新的狀態,而您必須對其進行測試。每個測試工具都承諾「簡單、不不穩定、快速」,但在細節上有所取捨。
領先的前端團隊如何跟上?他們的測試策略是什麼,他們使用什麼方法?我研究了 Storybook 社群中的十個團隊,以了解哪些方法有效——Twilio、Adobe、Peloton、Shopify 等。
這篇文章重點介紹了規模化工程團隊使用的 UI 測試技術。這樣,您可以創建一個務實的測試策略,以平衡覆蓋率、設定和維護。在此過程中,我們將指出要避免的陷阱。
我們正在測試什麼?
所有主要的 JavaScript 框架都是組件驅動的。這意味著 UI 是從「由下而上」構建的,從原子組件開始,逐步組合成頁面。
請記住,每個 UI 部分現在都是一個組件。是的,這包括頁面。頁面和按鈕之間唯一的區別在於它們如何消耗資料。
因此,測試 UI 現在與測試組件同義。

當涉及到組件時,不同測試方法之間的區別可能很模糊。與其關注術語,不如考慮 UI 的哪些特性需要測試。
- 視覺: 給定一組 props 或狀態,組件是否正確渲染?
- 組合: 多個組件是否協同工作?
- 互動: 事件是否按預期處理?
- 可訪問性: UI 是否可訪問?
- 使用者流程: 跨各種組件的複雜互動是否有效?
您應該關注哪裡?
全面的 UI 測試策略平衡了努力和價值。但是有這麼多測試方法,以至於很難弄清楚什麼適合任何給定的情況。這就是為什麼許多團隊使用以下標準評估不同的測試技術。
- 💰 維護成本: 編寫和維護測試所需的時間和精力。
- ⏱️ 迭代速度: 從進行更改到看到結果之間的回饋迴圈有多快。
- 🖼 真實環境: 測試執行的位置——在真實瀏覽器中還是像 JSDOM 這樣的模擬環境中。
- 🔍 隔離故障: 測試失敗,您可以多快識別故障來源。
- 🤒 測試不穩定性: 誤報/漏報破壞了測試的目的。
例如,端對端測試模擬「真實」使用者流程,但不適用於所有地方。在 Web 瀏覽器中測試的主要優勢也是一個缺點。測試執行時間更長,並且存在更多故障點(不穩定性!)。
現在我們已經介紹了要測試的 UI 特性和評估每種測試方法的標準,讓我們看看團隊如何設計他們的測試策略。
「測試讓我對自動化依賴項更新充滿信心。如果測試通過,我們就會將它們合併進來。」
— Simon Taggart,Twilio 首席工程師
視覺測試:這樣看起來對嗎?
現代介面有數不清的變化。您擁有的變化越多,就越難確認它們在使用者裝置和瀏覽器中都能正確渲染。
過去,您必須啟動應用程式,導航到頁面,並進行各種扭曲才能使 UI 進入正確的狀態。

組件結構允許您將特定變化渲染為 props 和狀態的函數。您無需啟動整個應用程式即可查看組件的渲染方式,而是傳遞 props 和狀態以隔離查看它。
Twilio 和 Shopify 使用 Storybook 來隔離組件,模擬它們的變化,並將支援的測試案例記錄為「stories」。這允許開發人員在初始開發期間以及在 QA 中再次快速檢查組件外觀。

儘管如此,考慮到應用程式的規模,手動測試 UI 外觀是不切實際的。您必須在每次調整 UI 時檢查每個組件在每個斷點和瀏覽器上的變化。這是一項繁重的工作!
Auth0 和 Radix UI 自動化了 UI 驗證過程。他們使用視覺化測試來捕獲每個 UI 組件的螢幕截圖,其中包含標記、樣式和其他資源,在一致的瀏覽器環境中。這樣,他們正在測試使用者實際看到的內容。
每次提交,新的螢幕截圖都會自動與先前接受的基準螢幕截圖進行比較。當機器檢測到視覺差異時,開發人員會收到通知,以批准有意的更改或修復意外的錯誤。

但是 DOM 快照測試呢?評估 HTML Blob 的缺點已被充分 記錄。
值得嗎?
總是值得的。視覺測試具有高價值和低成本。它們只需要最少的維護工作,在真實瀏覽器中執行,並且不穩定性低。
組合測試:這樣可以一起工作嗎?
當組件組合在一起時,往往會發生奇怪的事情。UI 由許多簡單的組件組成。驗證這些組件如何整合可確保系統作為一個整體正常運作。
但是測試組合很棘手,因為複雜的功能通常連接到資料和應用程式狀態。這需要您模擬或模擬應用程式的業務邏輯。

BBC 和 Sidewalk Labs (Google) 使用 Storybook 來隔離構建複合組件。Storybook 的擴充套件簡化了模擬資料、事件和 API 回應。一旦您的 UI 在 Storybook 中隔離,您就可以進行視覺化測試,以驗證組件整合,一直到頁面。



值得嗎?
經常值得。這些測試需要一些投入,但它們揭示了不明顯的整合問題,否則很難追蹤。
互動測試:當我按下這個按鈕時會發生什麼?
介面不是靜態的。使用者可以與 UI 互動、填寫表單欄位並觸發事件。
您如何確保 UI 正確回應互動?我們可以使用電腦來模擬和驗證使用者互動!

一種方法是使用像 Enzyme 這樣的工具來訪問組件的內部方法。然後觸發狀態更改並檢查結果。它有效,但您最終會測試內部運作方式,而不是像使用者那樣與 UI 互動。
這就是為什麼大多數團隊現在使用 Testing-Library,因為它評估組件輸出。它的工作原理是在虛擬瀏覽器 (JSDOM) 中渲染整個組件樹。它提供了模擬真實世界用法的實用程式。

Adobe 旨在通過將組件用例編寫為 stories 來進一步發展。然後在 Jest 中重用它們以運行互動測試。這由 Component Story Format 啟用——一種基於 JavaScript ES6 模組的可移植格式。因此,允許您在開發期間以及在視覺化、組合和互動測試中再次使用相同的 story。
值得嗎?
有時值得。互動測試確保組件之間的連接正常運作。事件正在流動,並且狀態正在更新。實際上,這意味著您可以通過編寫相對低維護成本的測試來獲得適度的覆蓋率。
可訪問性測試 – 應用程式是否適用於所有使用者?
您的使用者以多種方式與 UI 互動。例如,使用滑鼠、觸控螢幕、鍵盤和螢幕閱讀器。可訪問性是使網站對所有人可用的實踐。

測試可訪問性的最準確方法是在瀏覽器、裝置和螢幕閱讀器的組合中手動檢查它。公司通常聘請外部顧問或培訓內部人員。但這可能是不切實際的,因為手動測試每個 UI 更改都很耗時。這就是為什麼團隊使用混合方法,將手動測試和自動化結合起來。
作為 QA 的第一道防線,使用機器來捕獲明顯的可訪問性違規行為。這通過針對一組最佳實務啟發法(例如,使用像 Axe 這樣的庫)審核渲染的 DOM 來實現。在自動化檢查完成後,手動快速檢查 UI 以查找細微的問題。
結合自動化和手動最終成為覆蓋率和努力之間的務實平衡。您可以獲得快速的回饋迴圈,您可以在可訪問性問題影響生產環境之前找到並修復它們。大多數團隊使用 Axe 對組件運行自動化檢查。這也使他們能夠執行有針對性的測試以更快地發現錯誤。例如
- 原子組件: 評估鍵盤意識、不良顏色對比度或缺少 aria 屬性。
- 組合: 驗證組合組件不會互相妨礙行為。
- 頁面: 確保所有標題和各個部分都以正確的順序顯示。

Twilio Paste 團隊使用 jest-axe 整合來對組件運行自動化可訪問性審核。Axe 也可用作 Storybook 的外掛程式。
值得嗎?
總是值得。這不僅對您的使用者來說很棒,而且還是法律要求。Axe 是一種低投入的工具。使用它不會自動使您的應用程式可訪問,但它可以及早捕獲許多問題。
使用者流程測試 – 您的應用程式是否端對端正常運作?
即使是最基本的任務也需要使用者完成跨多個組件的一系列步驟。這是另一個潛在的故障點。像 Cypress 和 Playwright 這樣的工具允許您針對完整的應用程式運行端對端 (E2E) 測試,以驗證此類互動。

測試完整的應用程式需要大量的基礎設施工作。您必須創建一個測試環境,該環境並行部署系統的所有部分——前端、後端和其他服務。植入測試資料。然後連接到雲端瀏覽器以實際運行測試。
鑑於這些權衡,大多數團隊選擇放棄對其 UI 進行全面的 E2E 測試,而是傾向於互動和組合測試。或者他們將自己限制在少量 E2E 測試中,以確保應用程式在部署到生產環境後繼續正常運作。
但是,對於某些團隊來說,這種權衡是值得的。例如,O'Reilly 使用 Docker 來啟動他們的整個基礎設施。然後使用 Cypress 運行 E2E 測試以驗證使用者旅程。

值得嗎?
謹慎使用。E2E 測試需要大量的權衡。它們提供了高度的信心,但需要時間/精力來啟動和測試整個系統。因此,將 E2E 測試限制為僅關鍵使用者流程,例如,註冊 → 加入購物車 → 購買。
自動化無聊的部分
如果您像我一樣是開發人員,那麼構建 UI 比測試每個狀態更有趣。那麼,您如何在測試每個功能的同時仍然有時間編碼?
我採訪的每個團隊都使用持續整合 (CI) 伺服器來減少手動工作。每次您推送程式碼時,CI 都會自動觸發您的測試套件。測試在後台執行,結果會報告給 Pull Request 以供所有人審閱。
自動化 CI 檢查會自動檢測 UI 錯誤,以便在部署到生產環境之前讓您對 UI 的「外觀和感覺」充滿信心。

您的 UI 測試策略
UI 測試是交付高品質體驗不可或缺的一部分。弄清楚務實的測試策略可能會令人困惑,因為應用程式的表面積很大,並且有很多測試方法。
您最終會權衡取捨。有些測試易於維護,但提供虛假的保證。其他測試則將系統作為一個整體進行評估,但速度很慢。
在採訪了十個團隊以確定哪些 UI 測試方法實際有效後,我編制了他們推薦的工具的簡短列表。
- 📚 Storybook 用於將組件與其上下文隔離,以簡化測試。
- ✅ Chromatic 用於捕獲原子組件中的視覺錯誤並驗證組件組合/整合。
- 🐙 Testing Library 用於驗證互動和底層邏輯。
- ♿️ Axe 用於審核可訪問性
- 🔄 Cypress 用於驗證跨多個組件的使用者流程
- 🚥 GitHub Actions 用於持續整合
下表總結了每種 UI 測試方法的優缺點以及使用頻率。
到目前為止,本文僅觸及 UI 測試的表面。在即將發表的文章中,我將更深入地研究測試堆疊的每一層,並深入了解如何實施 UI 測試策略的機制。加入郵件列表以在發布更多測試文章時收到通知。
