文件
Storybook 文件

測試覆蓋率

測試覆蓋率是一種衡量現有測試是否完全覆蓋您的程式碼的做法。這表示找出目前未被測試的區域,例如:條件、邏輯分支、函數和變數。

覆蓋率測試會根據一套業界公認的最佳實務來檢查檢測過的程式碼。它們充當 QA 的最後一道防線,以提高您的測試套件的品質。

使用 Storybook Test

當您使用 Test 擴充套件執行元件測試時,該擴充套件由 Vitest 提供技術支援,它可以產生覆蓋率報告。結果會摘要在測試模組中,顯示您的已測試 Story 所涵蓋的語句百分比。

Screenshot of test module, expanded, showing coverage result

設定

覆蓋率已包含在 Test 擴充套件中,啟用後,在為您的專案執行元件測試時將會計算覆蓋率。若要啟用覆蓋率,請按下測試模組中的編輯按鈕(鉛筆圖示)並開啟覆蓋率切換鈕

Screenshot of test module, expanded, showing coverage toggle

在計算覆蓋率之前,您可能需要安裝與您的 覆蓋率提供者 相對應的支援套件

# For v8
npm install --save-dev @vitest/coverage-v8
 
# For istanbul
npm install --save-dev @vitest/coverage-istanbul

此外(在 Vitest 3.0.0 發佈之前),產生的覆蓋率報告將包含 Story 檔案本身以及您建置的 Storybook 應用程式的輸出。這會造成誤導,應該將它們排除在外。若要執行此操作,您可以將以下內容新增至您的 Vitest 設定

vitest.config.ts
import { coverageConfigDefaults, defineConfig } from 'vitest/config';
 
export default defineConfig({
  // ...
  test: {
    coverage: {
      // 👇 Add this
      exclude: [
         ...coverageConfigDefaults.exclude,
         '**/.storybook/**',
         // 👇 This pattern must align with the `stories` property of your `.storybook/main.ts` config
         '**/*.stories.*',
         // 👇 This pattern must align with the output directory of `storybook build`
         '**/storybook-static/**',
       ], 
    }
  }
})

用法

由於覆蓋率已內建於 Test 擴充套件中,因此您可以在執行測試的任何地方使用它。

Storybook UI

當您在 Storybook UI 中啟用覆蓋率時,覆蓋率報告將在您執行測試後產生並摘要在測試模組中。您可以看到已測試 Story 所涵蓋的語句百分比,以及覆蓋率是否達到 浮水印

此外,完整的覆蓋率報告將在您執行的 Storybook 的 /coverage/index.html 路由中提供。

務必瞭解 Storybook UI 中報告的覆蓋率有三個重要的限制

  1. 覆蓋率是使用您撰寫的 Story 計算的,而不是整個程式碼庫。換句話說,它不會包含任何其他 Vitest 測試。
  2. 覆蓋率只能針對您專案中的所有 Story 計算,而不能針對個別 Story 或 Story 群組計算。
  3. 啟用監看模式時,不會計算覆蓋率。啟用覆蓋率後,啟用監看模式將停用覆蓋率。

CLI

與 Storybook Test 的其餘部分一樣,覆蓋率建立在 Vitest 之上。這表示您可以使用 Vitest CLI 產生覆蓋率報告。

假設您使用如下的套件指令碼執行測試

package.json
{
  "scripts": {
    "test-storybook": "vitest --project=storybook"
  }
}

然後您可以使用以下命令產生覆蓋率報告

npm run test-storybook -- --coverage

覆蓋率報告將儲存到您專案中 設定的覆蓋率報告目錄(預設為 ./coverage)。

上述命令只會計算您撰寫的 Story 的覆蓋率,而不是整個程式碼庫。

由於在考量專案中的所有測試時,覆蓋率最準確,因此您也可以使用以下命令執行專案中所有測試的覆蓋率

npx vitest --coverage

編輯器擴充功能

覆蓋率也可透過 Vitest 的 IDE 整合取得。您可以直接在您的編輯器中計算和顯示覆蓋率結果。

Screenshot of test coverage in VSCode

請注意,此覆蓋率將包含您專案中的所有測試,而不僅僅是您撰寫的 Story。

CI

若要在您的 CI 管道中產生覆蓋率報告,您可以使用 CLI

例如,以下是簡化的 GitHub Actions 工作流程,用於執行您的測試並產生覆蓋率報告

.github/workflows/test-storybook.yml
name: Storybook Tests
on: push
jobs:
  test:
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'
      - name: Install dependencies
        run: yarn
      - name: Run Storybook tests
        run: yarn test-storybook --coverage

如需在 CI 中進行測試的詳細資訊,請參閱 Test 擴充套件文件

設定

覆蓋率提供者

您可以選擇要使用哪個提供者,v8(預設)或 Istanbul,來計算覆蓋率,方法是在您的 Vitest 設定中設定 coverage.provider 選項

vitest.config.ts
import { defineConfig } from 'vitest/config';
 
export default defineConfig({
  // ...
  test: {
    // ...
    coverage: {
      // ...
      provider: 'istanbul', // 'v8' is the default
    },
  },
});

浮水印

兩種覆蓋率提供者都支援 浮水印,即覆蓋率的閾值。低浮水印是通過測試所需的最低覆蓋率,而高浮水印是良好覆蓋率所需的最低覆蓋率。介於低浮水印和高浮水印之間的覆蓋率百分比將被視為可接受但不理想。

在測試模組中,覆蓋率摘要將顯示您的已測試 Story 所涵蓋的語句百分比,以及覆蓋率是否達到浮水印。低於低浮水印時,圖示將為紅色;介於低浮水印和高浮水印之間時,圖示將為橘色;高於高浮水印時,圖示將為綠色。

Screenshot of test module, expanded, showing coverage result

若要設定浮水印,您可以調整 Vitest 設定

vitest.config.ts
import { defineConfig } from 'vitest/config';
 
export default defineConfig({
  // ...
  test: {
    // ...
    coverage: {
      // ...
      watermarks: {
        // These are the default values
        statements: [50, 80],
      },
    },
  },
});

其他設定

您可以在 Vitest 文件中找到更多覆蓋率的設定選項。

在 Storybook UI 中計算覆蓋率時,以下選項始終會被忽略

  • enabled
  • clean
  • cleanOnRerun
  • reportOnFailure
  • reporter
  • reportsDirectory

使用覆蓋率擴充套件

觀看影片教學

Storybook 也提供 覆蓋率擴充套件。它由 Istanbul 提供技術支援,Istanbul 允許對 JavaScript 生態系統中最常用的框架和建置器進行開箱即用的程式碼檢測。

設定

覆蓋率擴充套件旨在與現代測試工具(例如,Playwright)協同工作,可自動檢測您的程式碼並產生程式碼覆蓋率資料。為了獲得最佳體驗,我們建議將 測試執行器 與覆蓋率擴充套件一起使用以執行您的測試。

執行以下命令以安裝擴充套件。

npx storybook@latest add @storybook/addon-coverage

CLI 的 add 命令會自動執行擴充套件的安裝和設定。若要手動安裝,請參閱我們關於如何安裝擴充套件的 文件

使用以下命令啟動您的 Storybook

npm run storybook

最後,開啟新的終端機視窗並使用以下命令執行測試執行器

npm run test-storybook -- --coverage

Coverage test output

設定

預設情況下,@storybook/addon-coverage 為 Storybook 提供零設定支援,並透過 istanbul-lib-instrumentWebpack 或透過 vite-plugin-istanbulVite 檢測您的程式碼。但是,您可以擴充您的 Storybook 設定檔(即 .storybook/main.js|ts)並為擴充套件提供其他選項。以下列出依建置器劃分的可用選項,以及如何使用它們的範例。

.storybook/main.ts
// For Vite support add the following import
// import type { AddonOptionsVite } from '@storybook/addon-coverage';
 
import type { AddonOptionsWebpack } from '@storybook/addon-coverage';
 
// Replace your-framework with the framework and builder you are using (e.g., react-webpack5, vue3-webpack5)
import type { StorybookConfig } from '@storybook/your-framework';
 
const coverageConfig: AddonOptionsWebpack = {
  istanbul: {
    include: ['**/stories/**'],
    exclude: ['**/exampleDirectory/**'],
  },
};
 
const config: StorybookConfig = {
  stories: [],
  addons: [
    // Other Storybook addons
    {
      name: '@storybook/addon-coverage',
      options: coverageConfig,
    },
  ],
};
 
export default config;
Vite 選項
選項描述類型
checkProd設定外掛程式以跳過生產環境中的檢測
options: { istanbul: { checkProd: true,}}
布林值
cwd設定覆蓋率測試的工作目錄。
預設為 process.cwd()
options: { istanbul: { cwd: process.cwd(),}}
字串
cypressVITE_COVERAGE 環境變數取代為 CYPRESS_COVERAGE
需要 Cypress 的 程式碼覆蓋率
options: { istanbul: { cypress: true,}}
布林值
exclude使用提供的檔案或目錄排除清單覆寫 預設排除清單,以從覆蓋率中排除
options: { istanbul: { exclude: ['**/stories/**'],}}
Array<String>string
extension使用提供的檔案副檔名清單擴充 預設副檔名清單,以包含在覆蓋率中
options: { istanbul: { extension: ['.js', '.cjs', '.mjs'],}}
Array<String>string
forceBuildInstrument設定外掛程式以在建置模式中新增檢測
options: { istanbul: { forceBuildInstrument: true,}}
布林值
include選取要收集覆蓋率的檔案
options: { istanbul: { include: ['**/stories/**'],}}
Array<String>string
nycrcPath定義現有 nyc 設定檔 的相對路徑
options: { istanbul: { nycrcPath: '../nyc.config.js',}}
字串
requireEnv透過授予對 env 變數的存取權,覆寫 VITE_COVERAGE 環境變數的值
options: { istanbul: { requireEnv: true,}}
布林值
Webpack 5 選項
選項描述類型
autoWrap透過將程式碼包裝在函數中,提供對最上層 return 語句的支援
options: { istanbul: { autoWrap: true,}}
布林值
compact壓縮檢測程式碼的輸出。對偵錯很有用
options: { istanbul: { compact: false,}}
布林值
coverageVariable定義 Istanbul 將用來儲存覆蓋率結果的全域變數名稱
options: { istanbul: { coverageVariable: '__coverage__',}}
字串
cwd設定覆蓋率測試的工作目錄。
預設為 process.cwd()
options: { istanbul: { cwd: process.cwd(),}}
字串
debug啟用偵錯模式以取得檢測過程中的其他記錄資訊
options: { istanbul: { debug: true,}}
布林值
esModules啟用對 ES Module 語法的支援
options: { istanbul: { esModules: true,}}
布林值
exclude使用提供的檔案或目錄排除清單覆寫 預設排除清單,以從覆蓋率中排除
options: { istanbul: { exclude: ['**/stories/**'],}}
Array<String>string
extension使用提供的檔案副檔名清單擴充 預設副檔名清單,以包含在覆蓋率中
options: { istanbul: { extension: ['.js', '.cjs', '.mjs'],}}
Array<String>string
include選取要收集覆蓋率的檔案
options: { istanbul: { include: ['**/stories/**'],}}
Array<String>string
nycrcPath定義現有 nyc 設定檔 的相對路徑
options: { istanbul: { nycrcPath: '../nyc.config.js',}}
字串
preserveComments在檢測程式碼中包含註解
options: { istanbul: { preserveComments: true,}}
布林值
produceSourceMap設定 Instanbul 為檢測程式碼產生來源地圖
options: { istanbul: { produceSourceMap: true,}}
布林值
sourceMapUrlCallback定義在產生來源地圖時使用檔案名稱和來源地圖 URL 叫用的回呼函數
options: { istanbul: { sourceMapUrlCallback: (filename, url) => {},}}
函數

其他覆蓋率報告工具呢?

程式碼覆蓋率測試可與 Storybook 的測試執行器和 @storybook/addon-coverage 無縫協作。但是,這並不表示您不能使用其他報告工具(例如,Codecov)。例如,如果您使用 LCOV,則可以使用產生的輸出(在 coverage/storybook/coverage-storybook.json 中)並使用以下命令建立您自己的報告

npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook

疑難排解

在其他框架中執行測試覆蓋率

如果您打算在具有特殊檔案的框架(例如 Vue 3 或 Svelte)中執行覆蓋率測試,則需要調整您的設定並啟用所需的檔案副檔名。例如,如果您使用 Vue,則需要將以下內容新增至您的 nyc 設定檔(即 .nycrc.jsonnyc.config.js

.nyc.config.js
export default {
  // Other configuration options
  extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue'],
};

覆蓋率擴充套件不支援最佳化建置

如果您使用 --test 旗標產生了針對效能最佳化的生產建置,並且您正在使用覆蓋率擴充套件來針對您的 Storybook 執行測試,則您可能會遇到覆蓋率擴充套件未檢測您的程式碼的情況。這是由於旗標的工作方式所致,因為它會移除對效能有影響的擴充套件(例如,Docs覆蓋率擴充套件)。若要解決此問題,您需要調整您的 Storybook 設定檔(即 .storybook/main.js|ts)並包含 disabledAddons 選項,以允許擴充套件以較慢的建置速度為代價執行測試。

.storybook/main.ts
// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
import type { StorybookConfig } from '@storybook/your-framework';
 
const config: StorybookConfig = {
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    '@storybook/addon-coverage',
  ],
  build: {
    test: {
      disabledAddons: ['@storybook/addon-docs', '@storybook/addon-essentials/docs'],
    },
  },
};
 
export default config;

覆蓋率擴充套件不支援檢測程式碼

由於 覆蓋率擴充套件 基於 Webpack5 加載器和 Vite 外掛程式進行程式碼檢測,因此不依賴這些程式庫的框架(例如,使用 Webpack 設定的 Angular)將需要額外設定才能啟用程式碼檢測。在這種情況下,您可以參考以下 儲存庫 以取得更多資訊。

瞭解其他 UI 測試