[note] React Testing
- Running Tests @ create-react-app
- react-testing-library @ testing-library
- 👍 React Testing Library Tutorial @ Youtube
- Day27 建立 Mock Module / Function 的方式(ft. TypeScript)
- Day28 測試依賴外層 Context Provider 的 React 元件:客製化 render 函式
- Day29 React Testing Library 的一些實用的小技巧
TL;DR
cheatsheet
- Custom Jest Matchers | Jest DOM: extends Jest matchers
- Queries | Dom Testing Library: methods provided by testing library
- Cheatsheet | React Testing Library
- Convenience APIs | User Event
$ npm test # 執行測試
$ npm test -- --coverage # 檢視測試覆蓋率
// 專注或略過某些測試
// https://pjchender.dev/npm/npm-jest/#專注和略過某些測試
test.only(() => {
/* ... */
});
test.skip(() => {
/* ... */
});
Snippets
// https://www.udemy.com/course/learn-react-query/learn/lecture/26581756
import { fireEvent, screen, waitForElementToBeRemoved } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { mockUser } from '../../../mocks/mockData';
import { render } from '../../../test-utils';
import { Calendar } from '../Calendar';
// mocking useUser hooks
jest.mock('../../user/hooks/useUser', () => ({
__esModule: true,
useUser: () => ({ user: mockUser }),
}));
test('Cancel appointment', async () => {
render(
<MemoryRouter>
<Calendar />
</MemoryRouter>,
);
const cancelButtons = await screen.findAllByRole('button', {
name: /cancel appointment/i,
});
fireEvent.click(cancelButtons[0]);
const alertToast = await screen.findByRole('alert');
expect(alertToast).toHaveTextContent('Appointment cancelled');
const alertCloseButton = screen.getByRole('button', { name: 'Close' });
fireEvent.click(alertCloseButton);
await waitForElementToBeRemoved(alertToast);
});
認識相關套件
- jsdom:一般也指測試的執行 環境(environment),目的是模擬瀏覽器的行為、API,讓開發者能在 Node.js 的環境下模擬瀏覽器的操作。其他這類的套件如 happy-dom。
- Jest:是一個用來執行 JavaScript 測試的框架(JavaScript Test Framework),又稱 test runner,它讓開發者能夠執行測試、撰寫斷言,提供的 API 像是
expect
、describe
、test
、toBe
、toEqual
等等。其他這類的 JS testing frameworks 如 Vitest、mochajs、Jasmine 等等 @testing-library/dom
:又稱作「DOM Testing Library」、「Web Testing Library」,是 Testing Library 的核心,一般如果講 Testing Library 就是在講這個。它讓開發者可以使用各種 queries 來找到 DOM Node(例如,getBy
、findBy
),使用 user-event(fireEvent)來觸發事件,其他與 Testing Library 相關的套件(例如,@testing-library/react
),多基於這個來添加功能。@testing-library/jest-dom
:原本 Jest 就有提供許多不同的 matchers(例如,toBe()
、toEqual()等等),
@testing-library/jest-dom則是擴充了更多可以在 Jest 中使用的 matchers,讓開發者可以使用
toBeInTheDocument()` 等這類和 DOM 有關的 matchers。@testing-library/react
:基於@testing-library/dom
,它讓開發者可以把 React 元件 render 到 DOM 上,像是render
、screen
、rerender
、unmount
等等。不需要搭配 Jest 才能使用。其他這類的工具如 Enzyme。@testing-library/user-event
:模擬使用者的操作來測試使用者與 UI 的互動。相較於@testing-library/dom
中的fireEvent
更能模擬使用者的行為。
warning
需要特別留意 @testing-library/dom
和 @testing-library/jest-dom
是兩個功能不同的套件。@testing-library/dom
是 Testing Library 的核心,@testing-library/react
即是基於它下去開發。@testing-library/jest-dom
則是替 Jest 提供了更多的 Matchers 可以使用,也就是說 @testing-library/jest-dom
是基於 Jest 的 Matchers。
ESLint Plugin
如果有使用 @testing-library
的話,也可以搭配使用他們提供的 ESLint plugin,例如 eslint-plugin-testing-library
和 eslint-plugin-jest-dom:
// .eslintrc.json
{
"overrides": [
{
"files": ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"],
"extends": ["plugin:testing-library/react", "plugin:jest-dom/recommended"]
}
]
}
前端測試(Testing)的概念
前端測試可以分成單元測試(unit testing)、整合測試(integration testing)和 end-to-end testing。詳細的說明可參考「前端測試的概念與類型」的內容。
單元測試(Unit Testing):以 Jest 為例
先從最基本的 Unit Test 開始。Unit Test 只需要使用 Jest 提供的方法即可完成,測試的起手式多半都是長這樣。使用 test
把要測試的內容包起來,Jest 則提供各種 method 可以幫你比對 expect 和 actual 之間是否相同。