返回部落格

故事即是測試

組件所有行為的單一事實來源

loading
Varun Vachhar
@winkerVSbecks
上次更新

想像一下,在沒有單元測試的情況下編寫複雜的函式。您將必須手動驗證每個情境,一遍又一遍。非常麻煩。然而,大多數團隊都是這樣構建 UI 的。他們調整一些程式碼,然後嘗試手動模擬每個 UI 狀態來檢查它。使用這種隨意的方法很容易遺漏錯誤。

Storybook 允許您採用更有組織的方法來構建 UI。您將組件的用例記錄為故事,然後將這些故事隔離呈現。這些故事就像單元測試,但用於呈現的組件。您實際上可以在瀏覽器中驗證呈現的輸出。

Storybook 是業界標準的組件 UI 開發工作坊。Netflix、Slack、Stripe 和全球數千個團隊都在使用它,因為它讓他們能夠為 UI 採用測試驅動的方法。讓我們看看如何做到。

具備眼球的單元測試

軟體瞬息萬變。您修復錯誤並發布新功能。但是,每次進行更改時都回去驗證每個組件是不現實的。尤其是在您沒有單元測試來協助您的情況下。

對比大多數團隊編寫非 UI 程式碼的方式。每個函式都有一套單元測試。它們在每次推送時執行,以捕捉迴歸錯誤。它們還允許開發人員清楚地思考程式碼在不同情境下需要做什麼。

然而,單元測試在 UI 方面失敗了,因為很難隔離組件,而且大多數測試工具不允許您(開發人員)以視覺方式驗證介面。

要測試函式,您可以使用像 Jest 這樣的框架。它使您能夠編寫定義完善的測試案例,並隔離執行每個案例。值得注意的是,測試在乾淨的環境中執行,而不是在應用程式中。

如果我們嘗試使用此基礎架構來測試組件,我們就會遇到一個大問題。這些測試沒有眼球!它們在 Node 中運行,可能使用 JSDOM。這意味著我們無法查看 UI 並驗證其外觀。為此,我們必須在真實的瀏覽器中單獨呈現每個組件。

我們需要的是編碼組件的貼紙表。
有沒有注意到設計師如何設定 Figma 或 Sketch 檔案?他們通常組裝一個符號網格。每個符號代表組件的一種狀態。每當設計師進行更改時,他們都可以快速驗證所有變體的正確性。

這就是 Storybook 為 UI 開發人員所做的事情。它編錄每個組件及其各種使用方式。組件被隔離呈現,以簡化開發和測試。

故事是視覺測試案例

一個測試包含三件事:設定、動作和斷言。讓我們分解 Storybook 的這個過程

  1. 設定: 每個故事描述組件的一個用例。您提供該狀態所需的適當 props 和資料。
  2. 動作: Storybook 在瀏覽器中呈現此組件。
  3. 斷言: 您以視覺方式檢查故事並手動測試互動。

在開發期間,您可以循環瀏覽故事以執行快速手動驗證。您實際上是在為介面編寫單元測試。一個視覺單元測試!

話雖如此,組件不僅僅是外觀。您還需要驗證其可訪問性、底層邏輯以及它如何融入更大的系統。故事是自動化和其他形式測試的起點。

一次編寫,處處測試

在我們開始之前,值得重新審視組件需要測試的不同特性

  1. 視覺: 給定一組 props 或狀態,組件是否正確呈現?
  2. 組合: 多個組件是否協同工作?
  3. 互動: 事件是否按預期處理?
  4. 可訪問性: UI 是否可訪問?
  5. 使用者流程: 跨各種組件的複雜互動是否有效?

有不同的工具可用於檢查這些方面的每一個。如果您獨立測試每個方面,您最終會一遍又一遍地複製組件狀態。這在設定和維護方面都很麻煩。

*.stories 檔案是組件如何使用的記錄。它是組件狀態的事實來源,這也是您想要在 UI 中測試的內容。它們使用基於 ES6 模組的互操作標準編寫,稱為組件故事格式。每個故事都作為 JavaScript 函式匯出,使您能夠將它們與其他工具重複使用。

您可以將它們與 Testing Library 一起使用,以驗證互動和底層邏輯。在 Chromatic 中進行視覺迴歸測試。或使用 Axe 來稽核可訪問性。或使用 Cypress 來測試使用者流程。所有這些都由同一組故事提供支援!

對於比簡單函式更複雜的組件呢?複雜的組件依賴於上下文、資料、應用程式狀態等等。一旦您在 Storybook 中配置了這些,您就可以在其他測試工具中重複使用該配置。

可移植的故事

Storybook 及其擴充功能生態系統允許您模擬資料、狀態甚至 API 響應。這使您能夠隔離構建和測試複雜的連接組件。更重要的是,您在 Storybook 中進行的任何設定都可以移植到其他測試工具。

@storybook/testing-react@storybook/testing-vue 套件提供了實用程式,用於提升所有包裝故事的提供者、上下文和裝飾器。您為隔離組件所做的所有配置都可以在 Jest、Cypress 等中重複使用。這是一個範例

import { render, screen } from '@testing-library/react';
import { composeStories } from '@storybook/testing-react';
import * as stories from './Button.stories';

/**
 * Every component that is returned maps 1:1 with the stories.
 * But, they also contain all decorators from story, meta and global levels.
 */
const { Primary, Secondary } = composeStories(stories);

test('renders primary button with default args', () => {
  render(<Primary />);
  const buttonElement = screen.getByText(
    /Text coming from args in stories file!/i
  );
  expect(buttonElement).not.toBeNull();
});

test('renders primary button with override props', () => {
  // You can override props and they will get merged with values from the Story's args
  render(<Primary>Hello world</Primary>);
  const buttonElement = screen.getByText(/Hello world/i);
  expect(buttonElement).not.toBeNull();
});
Button.test.js

當您將測試案例編寫為故事一次時,很容易在頂部疊加任何形式的斷言。

Storybook 是為 UI 測試而生的

在沒有單元測試的情況下開發組件不僅耗時更長,而且不可能捕捉到所有錯誤。通常很難模擬您想要涵蓋的所有測試案例。或者您可能會完全遺漏一種狀態。Storybook 使隔離呈現組件並探索其所有排列組合變得容易。讓您能夠為構建 UI 採用更有組織和測試驅動的方法。

故事檔案是組件所有重要用例的目錄。它是一個可移植的工件,允許您使用其他測試工具(例如 Testing Library、Jest 和 Axe)驗證互動、可訪問性和應用程式邏輯。

故事是組件的事實來源。它們允許您在開發期間快速檢查外觀。使用自動化捕捉迴歸錯誤或檢查功能品質。最後,為您的所有 UI 元素生成必要的文件

加入 Storybook 電子郵件列表

獲取最新的新聞、更新和發布

6,730開發人員及更多

我們正在招募!

加入 Storybook 和 Chromatic 背後的團隊。構建被數十萬開發人員在生產環境中使用的工具。遠端優先。

查看職位

熱門文章

組件故事格式 3.0

告別樣板程式碼,迎接腳本化互動!
loading
Michael Shilman

測試複合組件

防止小變更變成重大迴歸錯誤
loading
Varun Vachhar

Storybook 6.3

針對 UI 開發進行最佳化
loading
Michael Shilman
加入社群
6,730開發人員及更多
為何為何選擇 Storybook組件驅動的 UI
文件指南教學更新日誌遙測技術
社群擴充功能參與貢獻部落格
展示探索專案組件詞彙表
開放原始碼軟體
Storybook - Storybook 繁體中文

特別感謝 Netlify 以及 CircleCI