作为一个前端程序猿,在日常工作当中可能会遇到定制化地封装想要的组件的情况,此时我们写了很多行的代码,却并没有测试给我们回归,如果只靠我们自己保证质量,难免有漏掉的情况发生,这时单元测试的重要性就体现了。
当然了,在一些大的项目当中代码逻辑的正确性和功能性也尤为重要,此时完成一些功能后,我们也需要对其进行单元测试保证质量。
当我们按照整理好的需求还有设计文档完成了概要设计、文档书写和开发,在最后回归的时候可以按照文档和功能性对组件进行一定的测试,看看我们最终是否按照文档完成所有的功能和确保 JavaScript 代码的正确性。
接下来我们仔细看看单元测试
提到单元测试很多人会想到 Jest,那它有什么特性呢?
Jest 是 Facebook 开源的 JavaScript 测试框架,只需很少的配置,还能够根据需求进行扩展。
Jest 拥有自己独立的进程,最大限度地提高性能。
Jest 集成了断言、JSDom、覆盖率报告等开发者所需要的所有测试工具。通过添加
--coverage
标志生成代码覆盖率报告, 无需额外设置。Jest 可以从 整个项目收集代码覆盖面信息,包括未经测试的文件。Jest 拥有良好的文档,提供了易于理解、熟悉且功能丰富的 API 来编写测试用例,并快速地反馈结果。
接下来,我们来看看如何安装和使用:
安装
使用 yarn
安装
yarn add --dev jest
使用 npm
安装
npm install --save-dev jest
配置
在 package.json
中增加:
{
"scripts": {
"test": "jest"
}
}
常见命令:
{
"nocache": "jest --no-cache", //清除缓存
"watch": "jest --watchAll", //实时监听
"coverage": "jest --coverage", //生成覆盖测试文档
"verbose": "npx jest --verbose" //显示测试描述
}
在 jest.config.js
添加配置项
export default {
testMatch: ['<rootDir>/lib/**/__test__/**/*.[jt]s?(x)'],
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'node'],
collectCoverage: false, // 是否收集测试时的覆盖率信息(默认是false,同package配置的--coverage参数)
preset: 'ts-jest',
transform: {
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.tsx?$': 'babel-jest',
},
globals: {
'ts-jest': {
tsConfig: {
jsx: 'react',
},
},
},
testEnvironment: 'jsdom',
rootDir: ' ',
};
testMatch 识别哪些文件是测试文件
moduleFileExtensions 测试文件的类型
testEnvironment 测试环境,默认为
jsdom
,可修改为node
rootDir 当前目录,一般是
package.json
所在的目录
运行
最后使用 yarn test
或者 npm run test
运行
API
测试用例:
test(name, fn, timeout)
下面是一个测试用例,判断是否相等
test("this is a test",()=>{
expect({a:1}).toBe({a:1})
})
断言
当你想要测试一个值的时候,可以使用 expect
。
判断相等
toBe 是否等于
用来比较数字和字符串,不能用于浮点数
expect(value).toBe(value)
toBeCloseTo 是否等于
用于浮点数比较,numDigits
指检查小数点后几位数
expect(value).toBeCloseTo(number, numDigits?)
现在,来看看下面的一个例子:
// 结果是 Fails
expect(0.2 + 0.1).toBe(0.3);
// 下面是正确的写法
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
在 JavaScript 中,0.2 + 0.1 等于 0.30000000000000004。
toEqual 是否等于
用来比较数字、字符串、对象和数组,会递归的检查对象的所有属性和属性值是否相等,如果进行类型比较时,可以使用 toEqual
。
expect(value).toEqual(value)
toBeNull 是否等于 null
只匹配
null
expect(value).toBeNull()
toBeUndefined 是否等于 undefined
只匹配
undefined
expect(value).toBeUndefined()
包含
用来判断是否有包含关系
toHaveProperty 是否有对应属性
keyPath
代表对象的属性,value
代表属性的值
expect(value).toHaveProperty(keyPath, value?)
toContain 是否包含对应的值
括号里可以是数组或是字符串,生产当中可以用来检查数组中是否包含某一项。
expect(value).toContain(item)
toMatch 是否匹配对应的值
括号里可以是正则或是字符串
expect(value).toMatch(regexp | string)
toMatchObject 是否匹配对应的值
用来匹配对象和数组
expect(value).toMatchObject(object)
逻辑
用于逻辑判断,比如:大于、小于、是否为真等。
toBeTruthy 是否为真
可用来匹配 if 语句为真
expect(value).toBeTruthy()
toBeFalsy 是否为假
可用来匹配 if 语句为假
expect(value).toBeFalsy()
在 JavaScript 中,只有 6 种是假值,分别是:false,0,'',null,undefined 和 NaN。 其它的都是真值。
toBeGreaterThan 大于
使用 toBeGreaterThan
来进行大于的比较
expect(value).toBeGreaterThan(number | bigint)
toBeGreaterThanOrEqual 大于等于
使用 toBeGreaterThanOrEqual
来进行大于等于的比较
expect(value).toBeGreaterThanOrEqual(number | bigint)
toBeLessThan 小于
使用 toBeLessThan
来进行小于的比较
expect(value).toBeLessThan(number | bigint)
toBeLessThanOrEqual 小于等于
使用 toBeLessThanOrEqual
来进行小于等于的比较
expect(value).toBeLessThanOrEqual(number | bigint)
取反
测试不等于某个值的情况,not 后面可以是其它的断言
expect(value).not.toBe(value)
下面是一些使用的例子:
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
'nice.oven': true,
},
'ceiling.height': 2,
};
expect(houseForSale.bath).toBe(true);
expect(houseForSale.bedrooms).toEqual(4);
expect(houseForSale.kitchen).toBeNull();
expect(houseForSale.hello).toBeUndefined()
expect(houseForSale).toHaveProperty('bath');
expect(houseForSale).toHaveProperty('bedrooms', 4);
expect(houseForSale.kitchen.amenities).toContain('oven');
expect(houseForSale.kitchen.wallColor).toMatch(/white/);
expect(houseForSale.bath).toBeTruthy();
expect(houseForSale.bath).toBeFalsy();
expect(houseForSale.kitchen.area).toBeGreaterThan(18);
expect(houseForSale.kitchen.area).toBeLessThan(30);
expect(houseForSale).not.toHaveProperty('pool');
分组
describe(name, fn)
分组可以包含多个测试用例,即多个 test():
describe("component test",()=>{
test("this is a test",()=>{
......
})
test("this is b test",()=>{
......
})
......
})