成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Jest:給你的 React 項目加上單元測試

開發 前端
單元測試(Unit Testing),指的是對程序中的模塊(最小單位)進行檢查和驗證。比如一個函數、一個類、一個組件,它們都是模塊。

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

Jest 是一款輕量的 JavaScript 測試框架,它的賣點是簡單好用,由 facebook 出品。本文就簡單講講如何使用 Jest 對 React 組件進行測試。

為什么需要單元測試?

單元測試(Unit Testing),指的是對程序中的模塊(最小單位)進行檢查和驗證。比如一個函數、一個類、一個組件,它們都是模塊。

使用單元測試的優點:

  • 更好地交付高質量代碼。代碼不可能沒有 bug,測試能幫你找出來;
  • 更容易重構。我們不愿意去重構代碼,不去還技術債,很大原因是測試覆蓋率不足,害怕遺漏一些邊邊角角的邏輯,導致線上發生重大事故;
  • 可以用測試描述模塊功能。注釋和文檔容易忘記修改,但測試用例的描述永遠是準確的,因為不對就無法通過測試;
  • 可測試性好的代碼,往往可維護性更好。比如某個模塊很難測試,是因為它和其他模塊高度耦合,此時你需要替換為依賴注入的方式來管理模塊依賴。

Jest 判定測試腳本

Jest 需要 確認哪些是測試文件,默認判斷測試文件的邏輯是:

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

可以通過設置  Jest 配置文件的 testMatch 或 testRegex 選項進行修改,或者 package.json 下的 "jest" 屬性。

Jest 基本使用

我們先寫一個簡單的函數,作為被測試的模塊。

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

然后我們用 Jest 來做測試。

import sum from './sum';

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

然后執行 jest 命令,得到測試結果。

圖片

test 方法創建了一個測試的作用域,該方法有三個參數:

  1. 測試的描述。
  2. 我們寫測試代碼的函數。
  3. 測試超時時間,默認為 5 秒,有些測試是異步的,我們需要等待。

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

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

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

我們通常使用 expect 來測試一個模塊的邏輯是否符合預期。expect 會將模塊返回的結果封裝成一個對象,然后提供非常豐富的方法做測試。

比如 toBe 就可以做 Object.is 的對比測試。

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

expect 的實現思路大致為:

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

利用了閉包。

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

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

更多 API 可以看文檔:

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

你可以用 describe 方法將多個相關的 test 組合起來,這樣能讓你的測試用例更好地被組織,測試報告輸出也更有條理。

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

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

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

異步測試

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

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

或使用 async / await。

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

也支持回調函數風格的測試,你需要調用函數傳入的 done 函數來表明測試完成:

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

生命周期函數

beforeAll,在當前文件的正式開始測試前執行一次,適合做一些每次 test 前都要做的初始化操作,比如數據庫的清空以及初始化。

beforeEach,在當前文件的每個 test 執行前都調用一次。

afterAll,在當前文件所有測試結束后執行一次,適合做一些收尾工作,比如將數據庫清空。

afterEach,在當前文件的每個 test 執行完后都調用一次。

React Testing Library

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

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

執行單元測試的命令為:

yarn test

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

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

React Testing Library 的哲學是:

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

CreateReactApp 預置模板的 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

另一種比較流行的測試 React 組件的框架是  Enzyme,它的 API 簡潔優雅,能夠用類似 JQuery 的語法,對開發非常友好。Enzyme 由 Airbnd 出品,但目前已經不怎么維護了。

為此,你需要裝一些包:

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

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

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 測試 React 組件

我們先實現一個簡單的 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;

然后我們創建一個 button.test.tsx 測試文件。我們使用 React Testing Library。

我們寫個測試。

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 方法會將 React 組件掛載到虛擬的文檔樹上。screen.debug() 用于調試,能讓我們看到虛擬樹的完整結構。

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

測試 Button 的文本內容是否正常顯示:

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

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

測試 Button 的 onClick 能否正常觸發:

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

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

測試 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。

執行 yarn test :

圖片

結尾

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

責任編輯:姜華 來源: 前端西瓜哥
相關推薦

2020-03-19 14:50:31

Reac單元測試前端

2021-10-12 19:16:26

Jest單元測試

2017-01-14 23:42:49

單元測試框架軟件測試

2017-09-13 15:05:10

React前端單元測試

2017-09-10 17:41:39

React全家桶單元測試前端測試

2023-07-26 08:58:45

Golang單元測試

2011-05-16 16:52:09

單元測試徹底測試

2009-06-26 17:48:38

JSF項目單元測試JSFUnit

2011-07-27 17:02:12

Xcode iPhone 單元測試

2021-09-18 15:40:03

Vue單元測試命令

2017-01-14 23:26:17

單元測試JUnit測試

2017-01-16 12:12:29

單元測試JUnit

2011-06-14 15:56:42

單元測試

2022-05-12 09:37:03

測試JUnit開發

2020-08-18 08:10:02

單元測試Java

2021-05-05 11:38:40

TestNGPowerMock單元測試

2017-03-23 16:02:10

Mock技術單元測試

2011-07-04 18:16:42

單元測試

2020-05-07 17:30:49

開發iOS技術

2024-10-16 16:09:32

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产91丝袜在线播放 | 中文字幕第十一页 | 中文字幕1区2区3区 日韩在线视频免费观看 | 青青草国产在线观看 | 91在线精品一区二区 | 日韩毛片免费视频 | 91久久伊人| av午夜电影 | 免费的色网站 | 国产欧美在线播放 | 日韩精品免费播放 | 国产精品久久久久久久久污网站 | 午夜精品久久久久久久久久久久 | 久久精品国产a三级三级三级 | 国产日韩一区二区三区 | 完全免费在线视频 | 精品亚洲永久免费精品 | 中文字幕人成乱码在线观看 | av激情在线 | 成人一级毛片 | 91精品国产91久久久久久吃药 | 亚洲国产精品久久 | 精品无码久久久久久国产 | 成人小视频在线 | 久久国内| 91av入口| 色综合天天天天做夜夜夜夜做 | 久久三级av | 性色在线| 国产在线观看一区二区三区 | 一区二区在线免费播放 | 99精品欧美一区二区三区 | 日本粉嫩一区二区三区视频 | 中国av在线免费观看 | 久草网址 | 精品一区二区三区四区五区 | 国产精品99久久久久久宅男 | 亚洲97| 欧美自拍第一页 | 日韩中文在线 | 成人av一区二区在线观看 |