跳到主要内容

通过测试用例学习前端

· 阅读需 5 分钟

在现在前端工程化的时代,测试越来越显得不可或缺了。当我们封装好了一个些公共组件或类库,我们都要求书写相关功能的测试案例,当测试案例达到一定的覆盖率且都通过的时候才能保证我们封装组件或库是有质量保证,同时也避免开发人员在界面进行手动测试。

现如今前端的发展迅速,工具层出不穷,知识日新月异。要求前端工程师不断学习不断与时俱进(学不动了~),而当我们学习新知识的时候,通常都有把一些事例代码自己跑一遍的需求。

下面介绍一种通过书写测试案例的方式学习前端知识方法:下面就选择最近很火 React Hooks 作为学习的案例,测试框架选择 React 中常用的 JestTesting Library 组合的方式。当然你也可以选择 JestEnzyme,看个人喜好,但推荐使用 Testing Library,这也是 React 官方推荐的。

所以这里选择用 React Hook + Jest + Testing Library 的技术栈做一个 Hooks 的学习案例。

安装相关依赖

  • 安装 react 相关依赖
yarn add react react-dom
  • 安装 jest 相关依赖
yarn add --dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer
  • 安装 testing-libraray 依赖,选择 @testing-library/react-hooks@testing-library/react
yarn add --dev @testing-library/react

添加 test 命令

在项目目录的 package.json 文件中加上测试的 test 命令:

package.json
{
...
"scripts": {
"test": "jest"
}
...
}

添加测试案例

  • 在项目根目录新增 __tests__ 目录,用于存放我们测试案例。
  • __tests__ 的目录下新建 Hooks 的 useState 的测试案例文件 useState.test.js

编写测试案例:

/__tests__/useState.test.js
import React, { useState } from 'react';
import { cleanup, render, fireEvent } from '@testing-library/react';

afterEach(cleanup);

test('should work with useState', () => {
// 1. 定义函数组件 Example
function Example() {
// 2. 使用 useState Hook 定义状态变量 count 和更新函数 setCount
const [count, setCount] = useState(0);

return (
<div>
{/* 3. 添加 data-testid 用于获取节点*/}
<p data-testid="count">{count}</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

// 4. 渲染组件,从返回对象中取函数 getByTestId(通过 testid 获取节点) 和 getByText(通过文本获取节点)
const { getByTestId, getByText } = render(<Example />);
// 5. 断言当前 count 值为 0
expect(getByTestId('count').innerHTML).toEqual('0');

// 6. 触发 onClick 事件
fireEvent.click(getByText('Click me'));
// 7. 触发完事件后,断言 count 的值为 1
expect(getByTestId('count').innerHTML).toEqual('1');
});

然后我们在控制台中运行 test 命令:

yarn test

输出如下的信息表示我们测试案例是验证通过,如果不通过控制台会展示差别的代码。

$ jest
PASS __tests__/useState.test.js
✓ test react useState (35ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.387s
Ran all test suites.
✨ Done in 4.46s.

再添加一个 useEffect 的测试案例:

/__tests__/useEffect.test.js
test('should useEffect work', () => {
function Example() {
const [count, setCount] = useState(0);
// 相当于 componentDidMout 和 componentDidUpdate 的时候会更新文档标题
useEffect(() => {
document.title = `You clicked ${count} times`;
});

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
const { getByText } = render(<Example />);
expect(document.title).toEqual('You clicked 0 times');

fireEvent.click(getByText('Click me'));
expect(document.title).toEqual('You clicked 1 times');
});

这两个例子都非常简单,你可以再测试案例中把相对于 API 的所有功能都写一个测试案例进行学习,我在 CodeSanbox 中提供了这两个例子的代码,你可以在上面体验和尝试: