之前除了写 Go 的时候写写单元测试,前端 UI 测试属于一个很尴尬的地方,成本高而受益相对较低,一般出现错误很快就能在见面中呈现,而深度 BUG 需要写完整用例才能发现,但如果写很全面的测试用例需要用到的时间比写个组件还要浪费时间。
最近在参与组件库的开发,所以了解下 UI 测试,目前比较流行的是 Jest 和 Vitest,Vitest 算是比较新的产物,集成在了 Vite 里面,配置起来比较简单,Jest 需要使用 Babel 来转译。
另外,Chrome 其实也可以做测试,而且是自动化测试,非常适合一些业务场景或者复杂操作的自动测试需求。
如果你还在用 Webpack 那么可以继续使用 Jest,如果已经使用 Vite 了,那么可以直接上 Vitest 使用,两者的 API 差别不大,Vitest 基本就是参考 Jest 的 API 来写的。
我们的项目通常是基于 React 的,所以需要用到 @testing-library/react
这个库,由这个库处理 react 相关的东西到 js 对象,然后流转到 Vitest 基础测试库进行对比。
测试手段一般采用断言
,快照匹配
等方法来保证测试等有效性,断言即断定你这个代码执行后会如何如何,如下代码中断定可以获取到一个文本是 Hello 的元素。
const { container } = render(<Button>Hello</Button>)
expect(screen.getByText('Hello')).toBeDefined()
快照匹配会在第一次测试通过时保存一个 dom html 快照,之后有修改再次测试时会将渲染得到的结果和之前保存的 dom html 做对比,如果对比不一致机会不通过,当然快照后面修改 dom 结构时可以手动去更新。
// Vitest Snapshot v1
exports[`Button > button render 1`] = `
<button
class="ovo-ui-btn ovo-ui-btn-default"
>
Hello
</button>
`;
接下来简单介绍下使用 Vite + React 时如果使用 Vitest 进行测试。
第一步,安装需要的库:
npm i -D @testing-library/react jsdom vitest
第二步,配置启动脚本:
"scripts": {
...
"test": "vitest"
...
}
第三步,添加 test 文件
|-- __tests__
| `-- index.test.tsx
|-- button.less
|-- button.tsx
`-- index.tsx
// index.tsx
import { describe, test, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import Button from '../button'
describe('Button', () => {
test('button render', () => {
const { container } = render(<Button>Hello</Button>)
expect(screen.getByText('Hello')).toBeDefined()
expect(container.firstChild).toMatchSnapshot()
})
})
第四步,执行测试:
npm run test
启动后会保持监听模式,如果有相关修改会自动 rerun test,比如将断言中的 Hello 改为 Hello1,会自动运行测试并提示测试未通过。