关于安装
- create-react-app创建的应用自带Jest库,执行命令
npm run test
就会进入测试单元界面。同时提供强行运行所有单元测试代码、选择只用心满足过滤条件的单元测试用例等高级功能。 - 安装
npm install --save-dev jest babel-jest
或yarn add --dev jest babel-jest
关于使用
- 命名
- 文件名以.test.js为后缀的代码文件
- 存于test目录下的代码文件
为保持功能代码src目录整洁:在项目的根目录上创建一个名为test的目录,和存放功能代码的src的目录并列,在test目录下兼容和src对应子目录结构,每个单元测试文件以.test.js后缀,就能被Jest找到。缺点是单元测试中引用功能代码路径比较长。
将功能代码和测试代码放在一起对比容易;缺点就是散布在各个目录下的test看起来不是很整洁。
- 单元测试代码组织
单元测试代码的最小单位就是测试用例(test case),每个测试用例考验的是被测试对象在某些特定场景下是否有正确的行为。
每个测试用例一个it函数代表
参数:
- 字符串,代表测试用例名称:常用命名模式“被测对象在什么情况下是什么行为”
- 函数,实际测试用例过程
// it代表被测试对象,第一个参数描述它的预期行为
it('should return object when invoked', () = > {
// 增加断言语句
})
describe
为了测试被测试对象在多种情况下的行为,需要创建多个单元测试用例,这里需要用测试套件(test suite)构建,用来组织多个it函数实例。
测试套件可以嵌套使用:一个测试套件=测试用例+测试套件
测试套件和测试用例形成一个属性组织结构,执行顺序:从上到下,从里到外
describe('actions', () => {
it('should return object when invoked', () => {
})
// 可以有更多it函数调用
})
多个it放到一个describe中主要目的是为了重置共同环境设置。
describe中包含如下函数帮助重用代码:
- beforeAll 在开始测试套件之前执行一次
- afterAll 在结束测试套件中所有测试用例之后执行一次
- beforeEach 每个测试用例在执行之前都执行一次
- afterEach 每个测试用例在执行之后都执行一次
配置
- package.json中添加:
{
"scripts": {
"test": "jest --colors --coverage"
}
}
--coverage 可以生成测试覆盖率报告
--colors 根据覆盖率生成不同颜色的报告(<50%红色,50%~80%黄色, ≥80%绿色)
执行npm run test
命令可在终端运行查看测试运行结果。
- package.json中添加:
"jest": {
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"node_modules"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__jest__/__mocks__/fileMock.js",
"\\.(css|scss)$": "identity-obj-proxy",
"^cpn(.*)$": "<rootDir>/src/components$1"
}
}
moduleFileExtensions对应webpack中的extensions;
moduleDirectories对应webpack中的modulesDirectories;
moduleNameMapper对应webpack中的alias。这里的<rootDir>对应我们项目的根目录。
语法规则
- 普通匹配器
- toBe()
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});
- toEqual
匹配Object类型
test('object assignment', () => {
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
});
- 测试反向匹配
test('adding positive numbers is not zero', () => {
for (let a = 1; a < 10; a++) {
for (let b = 1; b < 10; b++) {
expect(a + b).not.toBe(0);
}
}
});
- Truthiness
在测试中,你有时需要区分 undefined、 null,和 false,但有时你又不需要区分。 Jest 让你明确你想要什么。
- toBeNull 只匹配 null
- toBeUndefined 只匹配 undefined
- toBeDefined 与 toBeUndefined 相反
- toBeTruthy 匹配任何 if 语句为真
- toBeFalsy 匹配任何 if 语句为假
test(name, () => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();
});
- 数字
test('two plus two', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);
// toBe and toEqual are equivalent for numbers
expect(value).toBe(4);
expect(value).toEqual(4);
});
test('两个浮点数字相加', () => {
const value = 0.1 + 0.2;
//expect(value).toBe(0.3); 这句会报错,因为浮点数有舍入误差
expect(value).toBeCloseTo(0.3); // 这句可以运行
});
- 字符串
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});
test('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/);
});
- 数组
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'beer',
];
test('the shopping list has beer on it', () => {
expect(shoppingList).toContain('beer');
expect(new Set(shoppingList)).toContain('beer');
});
例子
-
action 构造函数测试
步骤:
1. 预设参数
2. 调用纯函数
3. 用expect验证纯函数返回结果