文章

測試 React 應用

測試 React 應用

測試是一個確保 React 應用穩定性、可維護性的重要步驟。常見的 React 測試方法包括單元測試(Unit Testing)、組件測試(Component Testing)、端到端測試(End-to-End Testing)等。本文將介紹幾種常用的工具和技術來測試 React 應用。


1. 測試工具概覽

  • Jest:一個流行的 JavaScript 測試框架,內建於 Create React App 中,專為 React 應用設計,提供快速的單元測試支持。
  • React Testing Library:專注於測試 React 組件的行為,而非實現細節。
  • Cypress:一個用於端到端測試的框架,適合模擬用戶操作,測試整個應用流程。

2. 使用 Jest 和 React Testing Library 測試 React 組件

2.1 安裝 Jest 和 React Testing Library

在使用 Create React App 創建的應用中,Jest 已經默認安裝。如果你使用的是自定義設置,你需要安裝它們:

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

2.2 基本測試

讓我們從一個簡單的 React 組件開始,並編寫測試:

1
2
3
4
5
6
7
8
// Button.js
import React from 'react';

function Button({ onClick, children }) {
  return <button onClick={onClick}>{children}</button>;
}

export default Button;

編寫一個測試來驗證按鈕是否被渲染:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Button.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('渲染按鈕', () => {
  render(<Button>點擊我</Button>);
  const buttonElement = screen.getByText(/點擊我/i);
  expect(buttonElement).toBeInTheDocument();
});

test('點擊按鈕觸發事件', () => {
  const handleClick = jest.fn();
  render(<Button onClick={handleClick}>點擊我</Button>);

  const buttonElement = screen.getByText(/點擊我/i);
  fireEvent.click(buttonElement);

  expect(handleClick).toHaveBeenCalledTimes(1);
});
  • render:渲染組件。
  • screen.getByText:從渲染的 DOM 中查找特定文本內容的元素。
  • fireEvent.click:模擬按鈕點擊事件。
  • expect:斷言函數,檢查條件是否成立。

3. 測試表單和用戶輸入

假設我們有一個表單組件,可以通過 onSubmit 將輸入的值提交:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Form.js
import React, { useState } from 'react';

function Form({ onSubmit }) {
  const [value, setValue] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    onSubmit(value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="輸入內容"
      />
      <button type="submit">提交</button>
    </form>
  );
}

export default Form;

測試輸入和提交行為:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Form.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Form from './Form';

test('提交表單時調用 onSubmit 並傳遞輸入值', () => {
  const handleSubmit = jest.fn();
  render(<Form onSubmit={handleSubmit} />);

  const inputElement = screen.getByPlaceholderText(/輸入內容/i);
  const buttonElement = screen.getByText(/提交/i);

  fireEvent.change(inputElement, { target: { value: '測試內容' } });
  fireEvent.click(buttonElement);

  expect(handleSubmit).toHaveBeenCalledTimes(1);
  expect(handleSubmit).toHaveBeenCalledWith('測試內容');
});

這個測試模擬用戶在表單中輸入值並提交,並檢查 onSubmit 回調是否被正確調用。


4. Snapshot 測試

Snapshot 測試用於捕獲組件的渲染輸出,並與之前的輸出進行比較,檢查是否有意外的更改。

4.1 創建 Snapshot 測試

1
2
3
4
5
6
7
8
// Button.test.js
import { render } from '@testing-library/react';
import Button from './Button';

test('創建按鈕的 snapshot', () => {
  const { asFragment } = render(<Button>點擊我</Button>);
  expect(asFragment()).toMatchSnapshot();
});

當你運行測試時,Jest 會生成一個快照文件並將其與未來的渲染進行對比。如果渲染結果變更,測試會失敗,提示你檢查變更是否預期。


5. 使用 Cypress 進行端到端測試

5.1 安裝 Cypress

1
npm install cypress --save-dev

5.2 編寫端到端測試

假設我們有一個待測試的登錄頁面,端到端測試會模擬用戶輸入帳號密碼,點擊登錄按鈕,並驗證登錄成功。

1
2
3
4
5
6
7
8
9
10
11
12
// cypress/integration/login.spec.js
describe('登錄測試', () => {
  it('成功登錄', () => {
    cy.visit('http://localhost:3000/login'); // 打開應用

    cy.get('input[name="username"]').type('user123'); // 輸入用戶名
    cy.get('input[name="password"]').type('password123'); // 輸入密碼
    cy.get('button[type="submit"]').click(); // 點擊登錄按鈕

    cy.url().should('include', '/dashboard'); // 驗證是否成功跳轉
  });
});

這段測試將模擬一個完整的登錄過程,並檢查頁面是否正確跳轉到儀表板。


6. 總結

  • Jest:用於編寫單元測試和 Snapshot 測試。
  • React Testing Library:專注於組件的行為測試,適合測試 UI 和用戶交互。
  • Cypress:提供端到端測試,模擬用戶實際操作。

通過這些工具,開發者可以確保 React 應用的功能穩定,並降低引入 bug 的風險。

本文章以 CC BY 4.0 授權