跳至主要內容

執行測試

注意:此功能在 react-scripts@0.3.0 及更新版本中提供。

請閱讀遷移指南,以瞭解如何在較舊的專案中啟用這個功能!

建立 React 應用程式使用 Jest 作為測試執行器。為了準備進行這個整合,我們對 Jest 進行了 重大改造,因此如果您在幾年前聽過它的負面資訊,請再次嘗試。

Jest 是一個基於 Node 的執行器。這表示測試永遠在 Node 環境中執行,而不使用實際瀏覽器。如此一來,便能讓我們啟用快速的疊代速度並防止不穩定。

儘管 Jest 提供瀏覽器全域變數(例如 window),這要歸功於 jsdom,但它們只能近似真實的瀏覽器行為。Jest 是用於邏輯和元件的單元測試,而不是 DOM 怪癖。

我們建議,如果您有需要,請使用一個分開的工具進行瀏覽器端對端測試。這些功能不屬於建立 React 應用程式的範疇。

檔案命名慣例

Jest 會尋找使用下列任何熱門命名慣例命名的測試檔案

  • __tests__ 資料夾中,含有 .js 字尾的檔案。
  • 含有 .test.js 字尾的檔案。
  • 含有 .spec.js 字尾的檔案。

這些 .test.js / .spec.js 檔案(或 __tests__ 資料夾)可以位於 src 頂層資料夾下的任何深度。

我們建議將測試檔案(或 __tests__ 資料夾)放在要測試的程式碼旁邊,如此一來相對匯入的路徑看起來就比較短。例如,如果 App.test.jsApp.js 在同一個資料夾,測試只需要 import App from './App',而不用使用很長的相對路徑。和程式碼擺在一起也有助於在較大的專案中快速找到測試。

命令列介面

執行 npm test 時,Jest 會啟動監控模式*。每次儲存檔案時,Jest 都會重新執行測試,就像 npm start 重新編譯程式碼一樣。

監控器包含一個互動式命令列介面,能執行全部測試,或聚焦在搜尋模式。此設計用意是要讓使用者可以將監控器保持開啟狀態,並享受快速重新執行的功能。使用者可以從監控器於每個執行結束後列印的「監控使用說明」瞭解這些指令。

Jest watch mode

*雖然我們建議在開發期間於監控模式中執行測試,不過,使用者可以透過傳遞 --watchAll=false 旗標來停用此行為。大部分 CI 環境都會幫你處理好這件事(請參閱 CI 伺服器)。

版本控管整合

預設情況下,你執行 npm test 時,Jest 只會執行自上次提交以來有變更的檔案相關的測試。這是一個最佳化工具,旨在讓你的測試能夠高速執行,不管有多少個測試。但是,它假設你不會經常提交未通過測試的程式碼。

Jest 每次都會明確提到它只執行了自上次提交以來有變更的檔案相關的測試。你也可以在監控模式中按下 a,強制 Jest 執行所有測試。

如果專案並未位於 Git 或 Mercurial 儲存庫中,或是在 持續整合 伺服器上,Jest 會執行全部測試。

撰寫測試

若要建立測試,請加入 it()(或 test())區塊,並新增測試名稱及程式碼。你也可以選擇用 describe() 區塊將它們包起來以進行邏輯分組,但這不是必要做法,也不建議這麼做。

Jest 提供了一個內建的 expect() 全域函式來進行斷言。一個基本測試可以像以下這樣:

import sum from './sum';

it('sums numbers', () => {
expect(sum(1, 2)).toEqual(3);
expect(sum(2, 2)).toEqual(4);
});

Jest 支援的所有 expect() 比對器都已 在此廣泛記錄

你也可以使用 jest.fn()expect(fn).toBeCalled() 來建立「間諜程式」或模擬函式。

測試元件

有很多元件測試技術。這些技術涵蓋許多範圍,從驗證元件不發生錯誤的「煙霧測試」,到局部渲染和測試部分輸出,再到完整渲染和測試元件的生命週期和狀態變更。

專案選用不同的測試折衷方案,取決於元件變更的頻率與元件包含的邏輯量。如果您尚未決定好測試策略,建議您從為元件建立基本煙霧測試做起

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});

此測試會載入元件並確認元件在渲染過程中未發生錯誤。這類測試以非常少的精力發揮極大的價值,因此極適合作為起點,而且這是您會在 src/App.test.js 中找到的測試。

當您遇到因為變更元件而導致的錯誤時,您會更深入地了解要在專案中測試當中的哪些部分。這或許是引進更具體的測試(斷言特定預期輸出或行為)的好時機。

React Testing Library

如果您想在隔離這些元件所渲染的子元件的情況下測試元件,建議您使用 react-testing-libraryreact-testing-library 是一個可用與最終使用者使用元件相似的方式來測試 React 元件的函式庫。此函式庫很適合用於單元測試、整合測試和 React 元件與應用的端對端測試。由於它與 DOM 節點更直接地運作,因此建議搭配 jest-dom 使用,以改善斷言。

若要安裝 react-testing-libraryjest-dom,您可以執行

npm install --save @testing-library/react @testing-library/jest-dom

或者,您可以使用 yarn

yarn add @testing-library/react @testing-library/jest-dom

如果您想避免在測試檔案中產生樣板,可以建立一個 src/setupTests.js 檔案

// react-testing-library renders your components to document.body,
// this adds jest-dom's custom assertions
import '@testing-library/jest-dom';

這裡是使用 react-testing-libraryjest-dom 來測試 <App /> 元件會渲染「學習 React」的範例。

import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';

it('renders welcome message', () => {
render(<App />);
expect(screen.getByText('Learn React')).toBeInTheDocument();
});

進一步了解 react-testing-library 提供的公用程式,這些公用程式能促進非同步互動的測試,以及從 react-testing-library 文件範例 中選取表單元素。

使用協力廠商的斷言函式庫

我們建議您使用 expect() 針對斷言,並使用 jest.fn() 針對間諜。如果您對於這些方法感到困惑,請 針對 Jest 提出問題,我們會修正問題。我們打算持續改進這些方法,讓它們更適用於 React,舉例來說,將 React 元素以 JSX 的形式印出

但是,如果您習慣使用其他函式庫,例如 ChaiSinon,或者如果您有使用它們的現有程式碼想要移植,您可以像這樣正常匯入它們

import sinon from 'sinon';
import { expect } from 'chai';

然後像平時一樣在您的測試中使用它們。

初始化測試環境

注意:此功能可用於 react-scripts@0.4.0 及更高版本。

如果您的應用程式使用您需要在測試中模擬的瀏覽器 API,或者您需要在執行測試之前進行全域設定,請將 src/setupTests.js 加入您的專案。它將在執行您的測試之前自動執行。

例如

src/setupTests.js

const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;

注意:請記住,如果您決定在建立 src/setupTests.js 之前「彈出」,產生的 package.json 檔案將不會包含任何對它的參照,所以您應該手動為 Jest 的設定建立 setupFilesAfterEnv 屬性,如下所示

"jest": {
// ...
"setupFilesAfterEnv": ["<rootDir>/src/setupTests.js"]
}

將焦點放在測試上並排除測試

您可以將 it() 取代為 xit() 以暫時排除測試不執行。

同樣地,fit() 讓您可以將焦點放在特定測試上,而不執行其他任何測試。

涵蓋率報告

Jest 內建涵蓋率報告工具,適用於 ES6 且不需要任何設定。

執行 npm test -- --coverage(注意中間的額外 --)以包含如下所示的涵蓋率報告

coverage report

請注意,執行涵蓋率的測試速度會慢很多,因此建議您將其與您的正常工作流程分開執行。

設定

Create React App 用於 Jest 的 預設設定 可以透過在 package.json 中的 Jest 設定中加入下列任何受支援的鍵來覆寫。

受支援的覆寫

package.json 範例

{
"name": "your-package",
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,ts,tsx}",
"!<rootDir>/node_modules/",
"!<rootDir>/path/to/dir/"
],
"coverageThreshold": {
"global": {
"branches": 90,
"functions": 90,
"lines": 90,
"statements": 90
}
},
"coverageReporters": ["text"],
"snapshotSerializers": ["my-serializer-module"]
}
}

持續整合

預設情況下,npm test 會執行包含互動式 CLI 的監控。不過,你可以設定名為 CI 的環境變數,強制執行測試一次並完成處理程序。

使用 npm run build 建立應用程式建置時,並未預設檢查 Linter 警告。如同 npm test,你可以設定環境變數 CI,強制建置執行 Linter 警告檢查。如果發現任何警告,建置就會失敗。

熱門 CI 伺服器已經預設設定環境變數 CI,不過你也可以自己執行這些動作。

在 CI 伺服器上

Travis CI

  1. 依照 Travis 入門 指南將 GitHub 儲存庫與 Travis 同步。你可能需要在你的 個人檔案 頁面手動初始化一些設定。
  2. .travis.yml 檔案加入你的 git 儲存庫。
language: node_js
node_js:
- 8
cache:
directories:
- node_modules
script:
- npm run build
- npm test
  1. 使用 git push 觸發你的第一次建置。
  2. 如有需要,自訂你的 Travis CI 建置

CircleCI

依照 這篇文章,使用 Create React App 專案設定 CircleCI。

在你自己的環境中

Windows (cmd.exe)

set CI=true&&npm test
set CI=true&&npm run build

(注意:空白部分是故意的。)

Windows (Powershell)

($env:CI = "true") -and (npm test)
($env:CI = "true") -and (npm run build)

Linux、macOS (Bash)

CI=true npm test
CI=true npm run build

測試指令會強制 Jest 以 CI 模式執行,測試只會執行一次,而不是啟動監控。

對於非 CI 環境,你可以傳遞 --watchAll=false 標記以停用測試監控。

建置指令會檢查 Linter 警告,如果發現任何警告,就會失敗。

停用 jsdom

如果你知道你的測試內容皆不仰賴 jsdom,你可以安全地設定 --env=node,而你的測試就會執行得更快。

  "scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
- "test": "react-scripts test"
+ "test": "react-scripts test --env=node"

以下列出需要使用 jsdom 的 API,供你作為判斷依據。

相比之下,下列 API 不需要使用 jsdom

最後,快照測試 也不需要使用 jsdom。

快照測試

快照測試是 Jest 的一個功能,它會自動為元件產生文字快照,並儲存在磁碟中,因此如果 UI 輸出改變,您會在未撰寫任何元件輸出斷言的情況下收到通知。閱讀更多關於快照測試的資訊。

編輯器整合

如果您使用 Visual Studio Code,則有一個 Jest 擴充功能,它從一開始就支援 Create React App。如此一來,在使用文字編輯器的同時,可以提供許多類整合開發環境的功能:顯示測試執行狀態及潛在失敗訊息、自動啟動和停止監控程式,以及提供一鍵更新快照。

VS Code Jest Preview