自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Jest:給你的 React 項(xiàng)目加上單元測(cè)試

開發(fā) 前端
單元測(cè)試(Unit Testing),指的是對(duì)程序中的模塊(最小單位)進(jìn)行檢查和驗(yàn)證。比如一個(gè)函數(shù)、一個(gè)類、一個(gè)組件,它們都是模塊。

大家好,我是前端西瓜哥。

Jest 是一款輕量的 JavaScript 測(cè)試框架,它的賣點(diǎn)是簡(jiǎn)單好用,由 facebook 出品。本文就簡(jiǎn)單講講如何使用 Jest 對(duì) React 組件進(jìn)行測(cè)試。

為什么需要單元測(cè)試?

單元測(cè)試(Unit Testing),指的是對(duì)程序中的模塊(最小單位)進(jìn)行檢查和驗(yàn)證。比如一個(gè)函數(shù)、一個(gè)類、一個(gè)組件,它們都是模塊。

使用單元測(cè)試的優(yōu)點(diǎn):

  • 更好地交付高質(zhì)量代碼。代碼不可能沒有 bug,測(cè)試能幫你找出來;
  • 更容易重構(gòu)。我們不愿意去重構(gòu)代碼,不去還技術(shù)債,很大原因是測(cè)試覆蓋率不足,害怕遺漏一些邊邊角角的邏輯,導(dǎo)致線上發(fā)生重大事故;
  • 可以用測(cè)試描述模塊功能。注釋和文檔容易忘記修改,但測(cè)試用例的描述永遠(yuǎn)是準(zhǔn)確的,因?yàn)椴粚?duì)就無法通過測(cè)試;
  • 可測(cè)試性好的代碼,往往可維護(hù)性更好。比如某個(gè)模塊很難測(cè)試,是因?yàn)樗推渌K高度耦合,此時(shí)你需要替換為依賴注入的方式來管理模塊依賴。

Jest 判定測(cè)試腳本

Jest 需要 確認(rèn)哪些是測(cè)試文件,默認(rèn)判斷測(cè)試文件的邏輯是:

  • __tests__? 文件夾下的 .js  .jsx、.ts 、.tsx 為后綴的文件。
  • test.js? 、spec.js 或其他文件后綴  .jsx、.ts 、.tsx。

可以通過設(shè)置  Jest 配置文件的 testMatch 或 testRegex 選項(xiàng)進(jìn)行修改,或者 package.json 下的 "jest" 屬性。

Jest 基本使用

我們先寫一個(gè)簡(jiǎn)單的函數(shù),作為被測(cè)試的模塊。

function sum(a, b) {
return a + b;
}
export default sum;

然后我們用 Jest 來做測(cè)試。

import sum from './sum';

test('1 + 1 應(yīng)該等于 2', () => {
expect(sum(1, 1)).toBe(2);
});

然后執(zhí)行 jest 命令,得到測(cè)試結(jié)果。

圖片

test 方法創(chuàng)建了一個(gè)測(cè)試的作用域,該方法有三個(gè)參數(shù):

  1. 測(cè)試的描述。
  2. 我們寫測(cè)試代碼的函數(shù)。
  3. 測(cè)試超時(shí)時(shí)間,默認(rèn)為 5 秒,有些測(cè)試是異步的,我們需要等待。

test 方法有一個(gè)別名叫做 it,二者的功能是一致的,只是語義不同。通常用 test,但在某些情況下更適合用 it。這種情況就是 it 可以和描述語句拼成一句話的時(shí)候,比如:

it('should be true', () => { /* 測(cè)試內(nèi)容 */});

it 方法和后面的 should be true 拼成了一句主語為 it 的句子,語義更好。

我們通常使用 expect 來測(cè)試一個(gè)模塊的邏輯是否符合預(yù)期。expect 會(huì)將模塊返回的結(jié)果封裝成一個(gè)對(duì)象,然后提供非常豐富的方法做測(cè)試。

比如 toBe 就可以做 Object.is 的對(duì)比測(cè)試。

// sum(1, 1) 的結(jié)果是否為 2
expect(sum(1, 1)).toBe(2);

expect 的實(shí)現(xiàn)思路大致為:

function expect(value) {
return {
toBe(comparedValue) {
if (Object.is(value, comparedValue)) {
// 記錄測(cè)試成功
} else {
// 記錄測(cè)試失敗
}
},
// 其他 API
toBeTruthy() { /* ... */ },
// ...
}
}

利用了閉包。

還有一些其他的 toXX API,我們稱為 matcher。比如:

  • toEqual:對(duì)對(duì)象進(jìn)行深遞歸的 Object.is 對(duì)比。
  • toBeTruthy:是否為真值。
  • not:對(duì)結(jié)果取反,比如expect(val).not.beBe(otherVal) 表示兩值不相等才通過測(cè)試。
  • toContain:數(shù)組中是否含有某個(gè)元素。
  • toBeLessThan:是否小于某個(gè)值,可以做性能測(cè)試,執(zhí)行某個(gè)函數(shù)幾千次,時(shí)間不能高于某個(gè)值。

更多 API 可以看文檔:

??https://jestjs.io/docs/expect。??

你可以用 describe 方法將多個(gè)相關(guān)的 test 組合起來,這樣能讓你的測(cè)試用例更好地被組織,測(cè)試報(bào)告輸出也更有條理。

describe('一個(gè)有多個(gè)屬性的對(duì)象的測(cè)試', () => {
test('test 1', async () => {
expect(obj.a).toBeTruthy();
});

test('test 2', async () => {
expect(obj.b).toBeTruthy();
});
});

describe 里面可以嵌套 describe,即組里面還可以有組。

異步測(cè)試

如果使用異步測(cè)試,需要將 Promise 作為返回值。

test('請(qǐng)求測(cè)試', () => {
return getData().then(res {
expect(res.data.success).toBe(true);
})
})

或使用 async / await。

test('請(qǐng)求測(cè)試', async () => {
const res = await getData();
expect(res.data.success).toBe(true);
})

也支持回調(diào)函數(shù)風(fēng)格的測(cè)試,你需要調(diào)用函數(shù)傳入的 done 函數(shù)來表明測(cè)試完成:

test('異步測(cè)試', done => {
setTimeout(() {
expect('前端西瓜哥').toBeTruthy();
done();
}, 2000);
});

生命周期函數(shù)

beforeAll,在當(dāng)前文件的正式開始測(cè)試前執(zhí)行一次,適合做一些每次 test 前都要做的初始化操作,比如數(shù)據(jù)庫的清空以及初始化。

beforeEach,在當(dāng)前文件的每個(gè) test 執(zhí)行前都調(diào)用一次。

afterAll,在當(dāng)前文件所有測(cè)試結(jié)束后執(zhí)行一次,適合做一些收尾工作,比如將數(shù)據(jù)庫清空。

afterEach,在當(dāng)前文件的每個(gè) test 執(zhí)行完后都調(diào)用一次。

React Testing Library

本文不講解安裝和配置,我們先用 CreateReactApp 來搭建項(xiàng)目,并使用 TypeScript 模板。

yarn create react-app jest-app --template typescript

執(zhí)行單元測(cè)試的命令為:

yarn test

CreateReactApp 內(nèi)置了 Jest,但 Jest 本身并不支持 React 組件的測(cè)試 API,需要使用另外一個(gè)內(nèi)置的 React Testing Library 庫來測(cè)試  React 組件。

React Testing Library 是 以用戶為角度 的測(cè)試庫,能夠模擬瀏覽器的 DOM,將 React 組件掛載上去后,我們使用其提供的一些模擬用戶操作的 API 進(jìn)行測(cè)試。

React Testing Library 的哲學(xué)是:

測(cè)試的寫法越是接近應(yīng)用被使用的方式,我們就越有自信將其交付給客戶。

CreateReactApp 預(yù)置模板的 App.test.tsx 使用了 React Testing Library。

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

test('renders learn react link', () => {
render(<App);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

Enzyme

另一種比較流行的測(cè)試 React 組件的框架是  Enzyme,它的 API 簡(jiǎn)潔優(yōu)雅,能夠用類似 JQuery 的語法,對(duì)開發(fā)非常友好。Enzyme 由 Airbnd 出品,但目前已經(jīng)不怎么維護(hù)了。

為此,你需要裝一些包:

yarn add -D enzyme enzyme-adapter-react-16

如果你使用了 TS,你還得補(bǔ)上類型聲明。

yarn add -D @types/enzyme @types/enzyme-adapter-react-16

示例:

import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Button from '../button';
Enzyme.configure({ adapter: new Adapter() });
it('Button with children', () => {
const text = 'confirm';
const btn = shallow(<Button>{text}</Button>);
expect(btn.text()).toBe(text);
});

目前(2022.10.25) enzyme 官方只支持到 React 16,Enzyme 已死:

??https://dev.to/wojtekmaj/enzyme-is-dead-now-what-ekl。??

使用 Jest 測(cè)試 React 組件

我們先實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Button 組件。

import { CSSProperties, MouseEvent, FC } from 'react';
import classNames from 'classnames';
import './style.scss';

const clsPrefix = 'xigua-ui-btn';

export type ButtonProps = {
type?: 'primary' | 'default'
size?: 'large' | 'middle' | 'small';
disabled?: boolean;
children?: React.ReactNode;
onClick?: (event: MouseEvent) => void;
style?: CSSProperties;
className?: string;
}

const Button: FC<ButtonProps> = (props) => {
const {
type = 'default',
size = 'middle',
disabled = false,
children,
onClick,
style,
className,
} = props;

const mixedClassName = classNames(
clsPrefix,
`${clsPrefix}-${type}`,
`${clsPrefix}-${size}`,
className
);

return (
<button
style={style}
className={mixedClassName}
disabled={disabled}
onClick={onClick}
>
{children}
</button>
);
};

export default Button;

然后我們創(chuàng)建一個(gè) button.test.tsx 測(cè)試文件。我們使用 React Testing Library。

我們寫個(gè)測(cè)試。

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

test('Button with children', () => {
const text = 'confirm Btn';
render(<Button>{text}</Button>);

screen.debug();
});

render 方法會(huì)將 React 組件掛載到虛擬的文檔樹上。screen.debug() 用于調(diào)試,能讓我們看到虛擬樹的完整結(jié)構(gòu)。

<body>
<div>
<button
class="xigua-ui-btn xigua-ui-btn-default xigua-ui-btn-middle"
>
confirm Btn
</button>
</div>
</body>

測(cè)試 Button 的文本內(nèi)容是否正常顯示:

test('Button with children', () => {
const text = 'confirm Btn';
// 渲染 Button 組件
render(<Button>{text}</Button>);

// 找到內(nèi)容為 text 的元素
const BtnElement = screen.getByText(text);
// 測(cè)試元素是否在 Document 上
expect(BtnElement).toBeInTheDocument();
});

測(cè)試 Button 的 onClick 能否正常觸發(fā):

test('Button click', () => {
let toggle = false;
render(<Button onClick={() => { toggle = true; }} />);

// 找到第一個(gè) button 元素,然后觸發(fā)它的點(diǎn)擊事件
fireEvent.click(screen.getByRole('button'));
// 看看 toggle 變量是否變成 true
expect(toggle).toBe(true);
});

測(cè)試 Button 的 className 是否成功添加:

test('Button with custom className', () => {
const customCls = 'customBtn';
render(<button className={customCls} />);

// 找到按鈕元素
const btn = screen.getByRole('button');
// 元素的 className 列表上是否有我們傳入的 className
expect(btn).toHaveClass(customCls);
});

源碼:

??https://github.com/F-star/xigua-ui/blob/main/src/components/button/??tests/button.test.tsx。

執(zhí)行 yarn test :

圖片

結(jié)尾

為了讓代碼更健壯,做模塊的單元測(cè)試還是有必要的,Jest 作為流行的測(cè)試庫值得一試。

責(zé)任編輯:姜華 來源: 前端西瓜哥
相關(guān)推薦

2020-03-19 14:50:31

Reac單元測(cè)試前端

2021-10-12 19:16:26

Jest單元測(cè)試

2017-01-14 23:42:49

單元測(cè)試框架軟件測(cè)試

2017-09-13 15:05:10

React前端單元測(cè)試

2017-09-10 17:41:39

React全家桶單元測(cè)試前端測(cè)試

2023-07-26 08:58:45

Golang單元測(cè)試

2009-06-26 17:48:38

JSF項(xiàng)目單元測(cè)試JSFUnit

2011-07-27 17:02:12

Xcode iPhone 單元測(cè)試

2011-05-16 16:52:09

單元測(cè)試徹底測(cè)試

2017-01-14 23:26:17

單元測(cè)試JUnit測(cè)試

2017-01-16 12:12:29

單元測(cè)試JUnit

2021-09-18 15:40:03

Vue單元測(cè)試命令

2011-06-14 15:56:42

單元測(cè)試

2020-08-18 08:10:02

單元測(cè)試Java

2022-05-12 09:37:03

測(cè)試JUnit開發(fā)

2017-03-23 16:02:10

Mock技術(shù)單元測(cè)試

2021-05-05 11:38:40

TestNGPowerMock單元測(cè)試

2024-10-16 16:09:32

2011-07-04 18:16:42

單元測(cè)試

2020-05-07 17:30:49

開發(fā)iOS技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)