We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前端测试工具也和前端的框架一样纷繁复杂,其中常见的测试工具,大致可分为测试框架、断言库、测试覆盖率工具等几类。在正式开始本文之前,我们先来大致了解下它们:
测试框架的作用是提供一些方便的语法来描述测试用例,以及对用例进行分组。
测试框架可分为两种: TDD (测试驱动开发)和 BDD (行为驱动开发),我理解两者间的区别主要是一些语法上的不同,其中 BDD 提供了提供了可读性更好的用例语法,至于详细的区别可参见 The Difference Between TDD and BDD 一文。
常见的测试框架有 Jasmine, Mocha 以及本文要介绍的 Jest 。
断言库主要提供语义化方法,用于对参与测试的值做各种各样的判断。这些语义化方法会返回测试的结果,要么成功、要么失败。常见的断言库有 Should.js, Chai.js 等。
用于统计测试用例对代码的测试情况,生成相应的报表,比如 istanbul 。
Jest 是 Facebook 出品的一个测试框架,相对其他测试框架,其一大特点就是就是内置了常用的测试工具,比如自带断言、测试覆盖率工具,实现了开箱即用。
而作为一个面向前端的测试框架, Jest 可以利用其特有的快照测试功能,通过比对 UI 代码生成的快照文件,实现对 React 等常见框架的自动测试。
此外, Jest 的测试用例是并行执行的,而且只执行发生改变的文件所对应的测试,提升了测试速度。目前在 Github 上其 star 数已经破万;而除了 Facebook 外,业内其他公司也开始从其它测试框架转向 Jest ,比如 Airbnb 的尝试 ,相信未来 Jest 的发展趋势仍会比较迅猛。
Jest 可以通过 npm 或 yarn 进行安装。以 npm 为例,既可用npm install -g jest进行全局安装;也可以只局部安装、并在 package.json 中指定 test 脚本:
npm install -g jest
{ "scripts": { "test": "jest" } }
Jest 的测试脚本名形如*.test.js,不论 Jest 是全局运行还是通过npm test运行,它都会执行当前目录下所有的*.test.js 或 *.spec.js 文件、完成测试。
*.test.js
npm test
*.spec.js
表示测试用例是一个测试框架提供的最基本的 API , Jest 内部使用了 Jasmine 2 来进行测试,故其用例语法与 Jasmine 相同。test()函数来描述一个测试用例,举个简单的例子:
test()
// hello.js module.exports = () => 'Hello world'
// hello.test.js let hello = require('hello.js') test('should get "Hello world"', () => { expect(hello()).toBe('Hello world') // 测试成功 // expect(hello()).toBe('Hello') // 测试失败 })
其中toBe('Hello world')便是一句断言( Jest 管它叫 “matcher” ,想了解更多 matcher 请参考文档)。写完了用例,运行在项目目录下执行npm test,即可看到测试结果:
toBe('Hello world')
若测试失败,会标识出失败的断言位置,结果如下:
有时我们想在测试开始之前进行下环境的检查、或者在测试结束之后作一些清理操作,这就需要对用例进行预处理或后处理。对测试文件中所有的用例进行统一的预处理,可以使用 beforeAll() 函数;而如果想在每个用例开始前进行都预处理,则可使用 beforeEach() 函数。至于后处理,也有对应的 afterAll() 和 afterEach() 函数。
beforeAll()
beforeEach()
afterAll()
afterEach()
如果只是想对某几个用例进行同样的预处理或后处理,可以将先将这几个用例归为一组。使用 describe() 函数即可表示一组用例,再将上面提到的四个处理函数置于 describe() 的处理回调内,就实现了对一组用例的预处理或后处理:
describe()
describe('test testObject', () => { beforeAll(() => { // 预处理操作 }) test('is foo', () => { expect(testObject.foo).toBeTruthy() }) test('is not bar', () => { expect(testObject.bar).toBeFalsy() }) afterAll(() => { // 后处理操作 }) })
异步代码的测试,关键点在于告知测试框架测试何时完成,让其在恰当的时机进行断言。针对几种常见的异步代码形式, Jest 也提供了相应的异步测试语法。首先对于异步回调,向其传入并执行 done 函数, Jest 会等 done 回调执行结束后,结束测试:
done
// asyncHello.js module.exports = (name, cb) => setTimeout(() => cb(`Hello ${name}`), 1000)
// asyncHello.test.js let asyncHello = require('asyncHello.js') test('should get "Hello world"', (done) => { asyncHello('world', (result) => { expect(result).toBe('Hello world') done() }) })
此外,对于 Promise 控制的异步代码,可以直接在 then 回调中进行断言,只要保证在用例中返回该 Promise 对象即可:
then
// promiseHello.js module.exports = (name) => { return new Promise((resolve) => { setTimeout(() => resolve(`Hello ${name}`), 1000) }) }
// promiseHello.test.js let promiseHello = require('promiseHello.js') it('should get "Hello world"', () => { expect.assertions(1); // 确保至少有一个断言被调用,否则测试失败 return promiseHello('world').then((data) => { expect(data).toBe('Hello world') }) })
Jest 也支持 async/await 语法的测试,无需多余的操作,只要在 await 后进行断言即可,和同步测试的写法一致。
Jest 内置了测试覆盖率工具istanbul,要开启,可以直接在命令中添加 --coverage 参数,或者在 package.json 文件进行更详细的配置。
--coverage
运行 istanbul 除了会再终端展示测试覆盖率情况,还会在项目下生产一个 coverage 目录,内附一个测试覆盖率的报告,让我们可以清晰看到分支的代码的测试情况。比如下面这个例子:
// branches.js module.exports = (name) => { if (name === 'Levon') { return `Hello Levon` } else { return `Hello ${name}` } }
// branches.test.js let branches = require('../branches.js') describe('Multiple branches test', ()=> { test('should get Hello Levon', ()=> { expect(branches('Levon')).toBe('Hello Levon') }); // test('should get Hello World', ()=> { // expect(branches('World')).toBe('Hello World') // }); })
运行 jest --coverage 可看到产生的报告里展示了代码的覆盖率和未测试的行数:
jest --coverage
如果我们把branches.test.js中的注释去掉,跑遍测试对象中的所有分支,测试覆盖率就是100%了:
branches.test.js
针对前端框架的测试, Jest 的一大特色就是提供了快照测试功能。首次运行快照测试,会让 UI 框架生产一个可读的快照,再次测试时便会通过比对快照文件和新 UI 框架产生的快照判断测试是否通过。对于 React ,我们可以通过下面的方法生产一个快照:
import React from 'react'; import Link from '../Link.react'; import renderer from 'react-test-renderer'; it('renders correctly', () => { const tree = renderer.create( <Link page="http://www.facebook.com">Facebook</Link> ).toJSON(); expect(tree).toMatchSnapshot(); });
运行测试,我们可以看到生成一个快照文件如下:
exports[`renders correctly 1`] = ` <a className="normal" href="http://www.facebook.com" onMouseEnter={[Function]} onMouseLeave={[Function]} > Facebook </a> `;
这个可读的快照文件以可读的形式展示了 React 渲染出的 DOM 结构。相比于肉眼观察效果的 UI 测试,快照测试直接由Jest进行比对、速度更快;而且由于直接展示了 DOM 结构,也能让我们在检查快照的时候,快速、准确地发现问题。
除了 React ,Jest 文档中也提供了针对其他框架进行测试的指南。
如果你的项目中已经使用了别的测试框架,比如 Mocha,有一个第三方工具jest-codemods可以自动把用例迁移成 Jest 的用例,降低了迁移成本。
近几年前端工程化的发展风起云涌,但是前端自动化测试这块内容大家却似乎不太重视。虽然项目迭代过程中会有专门的测试人员进行测试,但等他们来进行测试时,代码已经开发完成的状态。与之相比,如果我们在开发过程中就进行了测试(直接采用 TDD 开发模式、或者针对既有的模块写用例),会有如下的好处:
当然,凡事都有两面性,好处虽然明显,却并不是所有的项目都值得引入测试框架,毕竟维护测试用例也是需要成本的。对于一些需求频繁变更、复用性较低的内容,比如活动页面,让开发专门抽出人力来写测试用例确实得不偿失。
而那些适合引入测试场景大概有这么几个:
Cypress 是专为现代网络打造的下一代前端测试工具,解决了开发人员和质量检查工程师在测试现代应用程序时面临的主要痛点。
UI测试 - 前端页面交互 单元测试 - 公共组件逻辑测试
聊一聊前端自动化测试
Web 前端单元测试到底要怎么写
jest单元测试入门
用 Jest 与 Puppeteer 进行 UI test
faker.js
cypress
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前端测试工具一览
前端测试工具也和前端的框架一样纷繁复杂,其中常见的测试工具,大致可分为测试框架、断言库、测试覆盖率工具等几类。在正式开始本文之前,我们先来大致了解下它们:
测试框架
测试框架的作用是提供一些方便的语法来描述测试用例,以及对用例进行分组。
测试框架可分为两种: TDD (测试驱动开发)和 BDD (行为驱动开发),我理解两者间的区别主要是一些语法上的不同,其中 BDD 提供了提供了可读性更好的用例语法,至于详细的区别可参见 The Difference Between TDD and BDD 一文。
常见的测试框架有 Jasmine, Mocha 以及本文要介绍的 Jest 。
断言库
断言库主要提供语义化方法,用于对参与测试的值做各种各样的判断。这些语义化方法会返回测试的结果,要么成功、要么失败。常见的断言库有 Should.js, Chai.js 等。
测试覆盖率工具
用于统计测试用例对代码的测试情况,生成相应的报表,比如 istanbul 。
Jest
为什么选择 Jest
Jest 是 Facebook 出品的一个测试框架,相对其他测试框架,其一大特点就是就是内置了常用的测试工具,比如自带断言、测试覆盖率工具,实现了开箱即用。
而作为一个面向前端的测试框架, Jest 可以利用其特有的快照测试功能,通过比对 UI 代码生成的快照文件,实现对 React 等常见框架的自动测试。
此外, Jest 的测试用例是并行执行的,而且只执行发生改变的文件所对应的测试,提升了测试速度。目前在 Github 上其 star 数已经破万;而除了 Facebook 外,业内其他公司也开始从其它测试框架转向 Jest ,比如 Airbnb 的尝试 ,相信未来 Jest 的发展趋势仍会比较迅猛。
安装
Jest 可以通过 npm 或 yarn 进行安装。以 npm 为例,既可用
npm install -g jest
进行全局安装;也可以只局部安装、并在 package.json 中指定 test 脚本:Jest 的测试脚本名形如
*.test.js
,不论 Jest 是全局运行还是通过npm test
运行,它都会执行当前目录下所有的*.test.js
或*.spec.js
文件、完成测试。基本使用
用例的表示
表示测试用例是一个测试框架提供的最基本的 API , Jest 内部使用了 Jasmine 2 来进行测试,故其用例语法与 Jasmine 相同。
test()
函数来描述一个测试用例,举个简单的例子:其中
toBe('Hello world')
便是一句断言( Jest 管它叫 “matcher” ,想了解更多 matcher 请参考文档)。写完了用例,运行在项目目录下执行npm test
,即可看到测试结果:若测试失败,会标识出失败的断言位置,结果如下:
用例的预处理或后处理
有时我们想在测试开始之前进行下环境的检查、或者在测试结束之后作一些清理操作,这就需要对用例进行预处理或后处理。对测试文件中所有的用例进行统一的预处理,可以使用
beforeAll()
函数;而如果想在每个用例开始前进行都预处理,则可使用beforeEach()
函数。至于后处理,也有对应的afterAll()
和afterEach()
函数。如果只是想对某几个用例进行同样的预处理或后处理,可以将先将这几个用例归为一组。使用
describe()
函数即可表示一组用例,再将上面提到的四个处理函数置于describe()
的处理回调内,就实现了对一组用例的预处理或后处理:测试异步代码
异步代码的测试,关键点在于告知测试框架测试何时完成,让其在恰当的时机进行断言。针对几种常见的异步代码形式, Jest 也提供了相应的异步测试语法。首先对于异步回调,向其传入并执行
done
函数, Jest 会等 done 回调执行结束后,结束测试:此外,对于 Promise 控制的异步代码,可以直接在
then
回调中进行断言,只要保证在用例中返回该 Promise 对象即可:Jest 也支持 async/await 语法的测试,无需多余的操作,只要在 await 后进行断言即可,和同步测试的写法一致。
测试覆盖率
Jest 内置了测试覆盖率工具istanbul,要开启,可以直接在命令中添加
--coverage
参数,或者在 package.json 文件进行更详细的配置。运行 istanbul 除了会再终端展示测试覆盖率情况,还会在项目下生产一个 coverage 目录,内附一个测试覆盖率的报告,让我们可以清晰看到分支的代码的测试情况。比如下面这个例子:
运行
jest --coverage
可看到产生的报告里展示了代码的覆盖率和未测试的行数:如果我们把
branches.test.js
中的注释去掉,跑遍测试对象中的所有分支,测试覆盖率就是100%了:在前端项目中使用
搭配React和其它框架
针对前端框架的测试, Jest 的一大特色就是提供了快照测试功能。首次运行快照测试,会让 UI 框架生产一个可读的快照,再次测试时便会通过比对快照文件和新 UI 框架产生的快照判断测试是否通过。对于 React ,我们可以通过下面的方法生产一个快照:
运行测试,我们可以看到生成一个快照文件如下:
这个可读的快照文件以可读的形式展示了 React 渲染出的 DOM 结构。相比于肉眼观察效果的 UI 测试,快照测试直接由Jest进行比对、速度更快;而且由于直接展示了 DOM 结构,也能让我们在检查快照的时候,快速、准确地发现问题。
除了 React ,Jest 文档中也提供了针对其他框架进行测试的指南。
无缝迁移
如果你的项目中已经使用了别的测试框架,比如 Mocha,有一个第三方工具jest-codemods可以自动把用例迁移成 Jest 的用例,降低了迁移成本。
后记:前端自动化测试,值不值得?
近几年前端工程化的发展风起云涌,但是前端自动化测试这块内容大家却似乎不太重视。虽然项目迭代过程中会有专门的测试人员进行测试,但等他们来进行测试时,代码已经开发完成的状态。与之相比,如果我们在开发过程中就进行了测试(直接采用 TDD 开发模式、或者针对既有的模块写用例),会有如下的好处:
当然,凡事都有两面性,好处虽然明显,却并不是所有的项目都值得引入测试框架,毕竟维护测试用例也是需要成本的。对于一些需求频繁变更、复用性较低的内容,比如活动页面,让开发专门抽出人力来写测试用例确实得不偿失。
而那些适合引入测试场景大概有这么几个:
扩展 Cypress
Cypress 是专为现代网络打造的下一代前端测试工具,解决了开发人员和质量检查工程师在测试现代应用程序时面临的主要痛点。
Other Resources
聊一聊前端自动化测试
Web 前端单元测试到底要怎么写
jest单元测试入门
用 Jest 与 Puppeteer 进行 UI test
faker.js
cypress
The text was updated successfully, but these errors were encountered: