Appearance
Jest 测试
提示
👉🏻 单元测试: 是指对软件中的最小可测试单元进行检查和验证 👉🏻 集成测试: 在单元测试的基础上,将所有模块按照设计要求组装成为子系统或系统,进行测试
1. 安装
javascript
yarn add -D jest
2. 快速上手
业务逻辑文件 index.js
javascript
// 非我举例,教程举例
function baojian1(money) {
return money > 200 ? '至尊享受' : '基本按摩'
}
function baojian2(money) {
return money > 1000 ? '双人服务' : '单人服务'
}
module.exports = { baojian1, baojian2 }
测试文件index.test.js
javascript
// import { baojian1, baojian2 } from './index'
const { baojian1, baojian2 } = require('./index')
test('大保健1--300', () => {
expect(baojian1(300)).toBe('至尊享受')
})
test('大保健2--2000', () => {
expect(baojian2(2000)).toBe('双人服务')
})
测试结果:
bash
PASS 01.第一次测试/index.test.js
✓ 大保健1--300 (2 ms)
✓ 大保健2--2000 (1 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.125 s, estimated 1 s
Ran all test suites.
✨ Done in 1.29s.
3. 基本配置文件
bash
npx jest --init
✔ Would you like to use Typescript for the configuration file? … no
# 是否使用TypeScript来配置jest配置文件?测试文件非ts选择no
✔ Choose the test environment that will be used for testing › jsdom (browser-like)
# 使用node环境还是浏览器环境来测试
✔ Do you want Jest to add coverage reports? … yes
# 是否希望Jest生成测试报告
✔ Which provider should be used to instrument code for coverage? › v8
# 应该使用哪个提供程序来检测覆盖范围的代码?
✔ Automatically clear mock calls, instances and results before every test? … yes
# 每次测试前自动清除模拟调用、实例和结果?
测试结果:
bash
PASS 01.第一次测试/index.test.js
✓ 大保健1--300 (1 ms)
✓ 大保健2--2000 (1 ms)
----------|---------|----------|---------|---------|-------------------
| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
| All files | 100 | 50 | 100 | 100 |
| index.js | 100 | 50 | 100 | 100 | 3,7 |
| ---------- | --------- | ---------- | --------- | --------- | ------------------- |
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.366 s
Ran all test suites.
✨ Done in 1.09s.
网页报表:
提示
👉🏻code coverage
,代码测试覆盖率,就是我们的测试代码,对功能性代码和业务逻辑代码作了百分多少的测试,这个百分比,就叫做代码测试覆盖率。
4. 匹配器
提示
👉🏻 代码中的undefined
, null
, and false
有不同含义,若你在测试时不想区分他们,可以用真值判断。
提示
👉🏻 对于比较浮点数相等,使用 toBeCloseTo
而不是 toEqual
,因为你不希望测试取决于一个小小的舍入误差。
匹配器 | 解释 |
---|---|
toBe() | 等同于=== 的,也就是我们常说的严格相等。 |
toEqual() | 等同于== 理解成只要内容相等,就可以通过测试 |
toBeNul() | 只匹配null 值,需要注意的是不匹配undefined 的值。 |
toBeUndifined() | 要匹配undefined 时,就可以使用,空字符串是没有办法通过测试的 |
toBeDefined() | 只要定义过了,都可以匹配成功 |
toBeTruthy() | 判断真假。真 则通过 |
toBeFalsy() | 同义,结果与上相反,假 则通过 |
toBeGreaterThan() | 只要大于传入的数值,就可以通过测试。 |
toBeLessThan() | 同义,结果与上相反 |
toBeGreaterThanOrEqual() | 数据大于等于期待数字时,可以通过测试。 |
toBeLessThanOrEqual() | 同义,结果与上相反 |
toBeCloseTo() | 自动消除 JavaScript 浮点精度错误的匹配器 |
toMatch() | 包含指定的字符串,可以通过测试,判断条件可以是字符串也可以是正则 |
toContain() | 同义,数组可用 |
toThrow() | 对异常进行处理的匹配器,可以检测一个方法会不会抛出异常。 |
not | 特殊的匹配器,意思就是相反或者说取反 |
... | 更多的匹配器请访问:https://jestjs.io/docs/expect |
5.自动监测
每次修改测试用例,我们都手动输入yarn test
,这显得很 lower。可以通过配置package.json
文件来设置。修改如下:
javascript
"scripts": {
"test": "jest --watchAll",
}
自动监测配置:
bash
Active Filters: filename /./02.匹配器//
› Press c to clear filters.
Watch Usage
› Press f to run only failed tests. # 只运行失败的测试
› Press o to only run tests related to changed files.# 只运行文件内容发生改变的测试
› Press p to filter by a filename regex pattern. # 按文件名正则表达式模式进行筛选
› Press t to filter by a test name regex pattern. # 似乎是按照文件名是否包含test进行筛选
› Press q to quit watch mode.# 退出监测模式
› Press Enter to trigger a test run.# 使用enter 开始测试
6.在 jest 中使用 import
目前我们的 Jest 是不支持import...from....
这种形式,如果使用就会报错,因为 Jest 默认支持的是CommonJS
规范,也就是Node.js
中的语法,他只支持require
这种引用。所以我们使用import...from...
是 ES6 的语法,所以使用就会报错。
解决方案:
6.1 安装 Babel 转换器
其实解决这个问题,直接使用 Babel 就可以把代码转换成CommonJS
代码,然后就可以顺利进行测试了。那现在就来安装一下Babel
.
javascript
yarn add -D @babel/core@7.4.5 @babel/preset-env@7.4.5
6.2 配置.babelrc 文件
我们在项目根目录下新建一个.babelrc
的文件,作为一个前端,你对这个文件应该是非常熟悉的,babel 的转换配置就写在这个文件里。
javascript
{
"presets":[
[
"@babel/preset-env",{
"targets":{
"node":"current"
}
}
]
]
}
当你写完这段代码后,就可以进行转换了。我们再次使用yarn test
进行测试,这时候就可以正确通过测试了。也就是说我们用的babel
起到作用了。
那为什么会这样那?其实在Jest
里有一个babel-jest
组件,我们在使用yarn test
的时候,它先去检测开发环境中是否安装了babel
,也就是查看有没有babel-core
,如果有bable-core
就会去查看.babelrc
配置文件,根据配置文件进行转换,转换完成,再进行测试。
7. 测试异步函数
需要前置axios
模块
bash
yarn add axios
7.1 普通异步
新建一个文件index.js
文件,然后编写代码如下:
javascript
import axios from 'axios'
const URL = 'http://39.98.123.211/api/user/passport/login'
export function getData(callback) {
axios.get(URL).then(response => callback(response))
}
这是我们最经常使用的一种异步请求方法的形式,接着新建一个index.test.js
的测试文件,编写代码如下:
javascript
import { getData } from './index'
test('异步测试', done => {
getData(data => {
try {
const _data = JSON.stringify(data)
// TODO: 接口返回的是json,只能暂时先转换为字符串然后匹配,看后期有什么优化的空间
expect(_data).toMatch('"status":200')
done()
} catch (err) {
done(err)
}
})
})
7.2 测试返回结果为 Promise 对象
有时候会直接返回一个promise
值,这样的方法在工作中也式经常使用的。
javascript
// 被测试单元
import axios from 'axios'
const URL = 'http://39.98.123.211/api/user/passport/login'
export const getDataTwo = () => {
return axios.get(URL)
}
测试代码:
javascript
import { getData, getDataTwo } from './index'
test('Promise测试', () => {
return getDataTwo().then(res => {
// const _res = JSON.stringify(res)
expect(res).toMatchObject({ status: 200 })
console.log('测试通过')
})
})
7.3 指定测试结果状态
在特殊需求中,需要将原本不通过测试的状态改为通过
javascript
// 被测试单元
import axios from 'axios'
const URL = 'http://39.98.123.211/api/user/passport/login'
export const getDataTwo = () => {
return axios.get(URL)
}
测试代码:
javascript
import { getData, getDataTwo } from './index'
test('Promise测试捕获异常,使其通过测试', () => {
expect.assertions(1) // 断言,使其必须走一次测试流程,如果结果正常,则会报错,因为这是专门测试异常的测试条件
return getDataTwo().catch(err => {
// console.log(err.toString())
expect(err.toString().includes('404')).toBeTruthy()
})
})
7.4 对 async ... aswit 测试
javascript
// 被测试文件
import axios from 'axios'
const URL = 'http://39.98.123.211/api/user/passport/login'
export const getDataTwo = () => {
return axios.get(URL)
}
测试文件:
javascript
test('asyc...await测试', async () => {
const res = await getDataTwo()
expect(res).toMatchObject({ status: 200 })
console.log('asyc...await测试通过')
})