前端自动化测试框架--jest
概要:
常见的测试工具,大致可分为测试框架、断言库、测试覆盖率工具等几类。
测试框架的作用是提供一些方便的语法来描述测试用例,以及对用例进行分组。
测试框架可分为两种: TDD (测试驱动开发)和 BDD (行为驱动开发)
常见的测试框架有 Jasmine, Mocha 以及本文要介绍的 Jest
断言库:主要提供语义化方法,用于对参与测试的值做各种各样的判断。这些语义化方法会返回测试的结果,要么成功、要么失败。
常见的断言库有 Should.js, Chai.js 等。
测试覆盖率工具:用于统计测试用例对代码的测试情况,生成相应的报表,比如 istanbul
1、什么是Jest
Jest 是 Facebook 出品的一个测试框架,
相对其他测试框架,其一大特点就是就是内置了常用的测试工具,比如自带断言、测试覆盖率工具,实现了开箱即用。
而作为一个面向前端的测试框架,
Jest优点:比较新,基础很好,速度快,API简单,隔离性好,IDE整合,多项目并行,快出覆盖率
2、安装与配置
npm install --save-dev jest 或者 yarn add --dev jest
3、简单试用
在根目录下,新建2个文件,sum.js 和 sum.test.js
sum.js中:
function sum(a, b){
return a + b;
}
module.exports = sum;
sum.test.js中:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
})
package.json 配置测试启动脚本
{
"scripts": {
"test": "jest"
}
}
运行yarn test 或 npm run test
Jest将打印以下信息:
PASS ./sum.test.js
√ adds 1 + 2 to equal 3 (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.396 s
Ran all test suites.
4、基本配置和测试覆盖率生成
单元测试和集成测试的区别:
单元测试:英文是(unit testing) 单,是指对软件中的最小可测试单元进行检查和验证。
前端所说的单元测试类似于模块测试。
集成测试:也叫组装测试或者联合测试。
在单元测试的基础上,将所有模块按照涉及要求组装成为子系统或系统,进行集成测试。
4.1 Jest 初始化配置: npx jest –init
之后,你会发现你的工程根目录下多了一个jest.config.js的文件
4.2 coverageDirectory : “coverage”, //打开测试覆盖率选项
打开上面的jest配置文件,coverageDirectroy的配置是用来打开代码覆盖率的,
当这个选项被打开后,我们就可以使用下面的命令,jest就会自动给我们生成一个代码测试覆盖率的说明。
4.3 npx jest –coverage
当然这个不仅会有一个简单的终端图表,还会生成一个coverage的文件夹,这里边有很多文件。
PASS ./sum.test.js
√ adds 1 + 2 to equal 3 (2 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
sum.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
我们可以打开coverage-lcov-reporrt-index.html文件,这时候就可以看到一个网页形式的,非常漂亮的测试覆盖率报告。
5、jest匹配器
5.1、 toBe()匹配器:严格相等匹配
test('测试toBe的匹配',()=>{
expect('toBe的匹配').toBe('toBe的匹配')
})
test('测试严格相等',()=>{
const a = {number:'007'}
expect(a).toBe({number:'007'})
})
第一个代码块 通过,第二个失败(仅内容相等)
5.2、 toEqual()匹配器:非严格相等匹配
test('测试严格相等',()=>{
const a = {number:'007'}
expect(a).toEqual({number:'007'})
})
结果通过
5.3、toBeNul()匹配器:只匹配null值
test('toBeNull测试',()=>{
const a = null
expect(a).toBeNull()
})
5.4、toBeUndefined()匹配器 :只匹配undefined值
5.5、 toBeDefined()匹配器:只要定义过了,则可以匹配成功
5.6、toBeTruthy()匹配器/toBeFalsy()匹配器:true/false匹配器,相当于判断真假
5.7、toBeGreaterThan()匹配器/toBeLessThan()匹配器:数值比较,大于/小于 传入的数值,则通过
5.8、toBeGreaterThanOrEqual()匹配器/toBeLessThanOrEqual()匹配器:大于等于/小于等于,则通过
5.9、toBeCloseTo()匹配器:自动消除浮点精度错误
5.10、toMatch()匹配器:字符串包含
5.11、toContain()匹配器:数组包含
5.12、toThrow()匹配器:异常处理
5.13、not匹配器:取反
6、jest支持import和Es6语法
jest默认支持CommonJs规范,也就是Nodejs语法,只支持require引用,而Es6引用为import…from。
解决方案:使用Babel将代码块从Es6转换为CommonJs
npm install @babel/core@7.4.5 @babel/preset-env@7.4.5 -D
或者
yarn add @babel/core@7.4.5 @babel/preset-env@7.4.5 -dev
Babel基本配置:
在项目根目录下新建一个.babelrc的文件
{
"presets":[
[
"@babel/preset-env",
{
"targets":{
"node":"current"
}
}
]
]
}
结果通过
7、异步代码的测试方法
7.1、回调函数式
安装axios
npm install axios@0.19.0 --save 或者 yarn add axioss@0.19.0
根目录下,新建 fetchData.js,并编写:
import axios from 'axios'
export const fetchData = (fn)=>{
axios.get('http://xxx.com/xxx.json').then((response)=>{
fn(response.data)
})
}
新建fetchData.test.js,并编写:
import { fetchData } from './fetchData.js'
test('fetchData 测试',(done)=>{
fetchData((data)=>{
expect(data).toEqual({
success: true
})
done()
})
})
7.2、直接返回promise
fetchData.js:
import axios from 'axios'
export const fetchTwoData = ()=>{
return axios.get('http://xxx.com/xxx.json')
}
fetchData.test.js:
import { FetchTwoData } from './fetchData.js'
test('FetchTwoData 测试', ()=>{
return fetchTwoData().then((response)=>{
expect(response.data).toEqual({
success: true
})
})
})
7.3、不存在的接口的测试方法
fetchData.test.js:
import { FetchThreeData } from './fetchData.js'
test('FetchThreeData 测试', ()=>{
expect.assertions(1) // 断言,必须执行一次expect
return fetchThreeData().catch((e)=>{
expect(e.toString().indexOf('404')> -1).toBe(true)
})
})
7.4、async….await
fetchData.test.js:
import { FetchFourData } from './fetchData.js'
test('FetchFourData 测试', async()=>{
//resolves把现有对象转换成Promise对象,
//toMatchObject 匹配对象中的属性
await expect(fetchFourData()).resolves.toMatchObject({
data:{
success:true
}
})
})
或者
import { FetchFourData } from './fetchData.js'
test('FetchFourData 测试', async()=>{
const response = await fetchFourData()
expect(response.data).toEqual({
success : true
})
})
8、jest的4个钩子函数
beforeAll()钩子函数:在所有测试用例之前进行执行
afterAll()钩子函数:在完成所有测试用例之后才执行
beforeEach()钩子函数:在每个测试用例前都会执行一次
afterEach()钩子函数:在每个测试用例完成测试之后执行一次
9、jest对测试用例进行分组
describe('参数1',()=>{
.....
})