使用jest写JavaScript测试

jestfacebook 出的一个 JavaScript 测试框架,特点就是:

  • 配置简单
  • 内置代码覆盖率报告
  • 强大的模拟库
  • 高速和沙盒

安装

通过npm 或者yarn 来安装Jest︰

1
2
3
4
5
6
7
8
9
10
mkdir jest-study
cd jest-study
npm init
npm install --save-dev jest
// 或者
yarn add --dev jest
// 在package.json里添加scripts
{
"test": "jest --coverage"
}

使用

首先,我们来编写一个函数:

1
2
3
4
5
6
touch sum.js
# 内容如下
function sum(a, b) {
return a + b;
}
module.exports = sum;

jest支持三种方式写测试代码:

  1. 使用 .spec.js后缀
  2. 使用.test.js后缀
  3. 放在__tests__文件夹下

测试代码如下:

1
2
3
4
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});

最后运行npm test查看结果。

Jest配置

jest希望默认的配置就可以完全满足需求,但有时候如果有些特殊要求,比如忽略某个文件,指定环境等,还是需要配置,jest配置有两种方式

  1. 直接在package.json里添加jest字段
  2. 创建jest.config.js配置文件,然后通过 --config<path/to/js|json> 选项传递进来

Jest CLI 选项

  1. 仅运行符合指定用模板或文件名的测试︰

    1
    2
    jest my-test #or
    jest path/to/my-test.js
  2. 仅检测git (未提交的文件) 修改的文件的测试

    1
    jest -o
  3. 运行监视模式

    1
    2
    jest --watch #runs jest -o by default
    jest --watchAll #runs all tests

使用Babel

jest是不能解析ES6的代码的,所以需要babel来编译。

1
2
3
4
5
6
npm install --save-dev babel-jest
touch .babelrc
# 粘贴下面内容
{
"presets": ["es2015", "react"]
}

当你安装 Jest 时,babel-jest 是会被自动安装的,并且如果你的项目下存在一个 Babel 配置文件时,它将会自动对相关文件进行转义。 如果要避免这个行为,你可以显式的重置 transform 配置项

结合Enzyme

Enzymeairbnb公司出的一款实用的react测试框架。结合如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// package.json
{
"dependencies": {
"react": "15.4.2",
"react-dom": "15.4.2"
},
"devDependencies": {
"babel-jest": "*",
"babel-preset-env": "*",
"babel-preset-react": "*",
"enzyme": "*",
"jest": "*",
"react-addons-test-utils": "15.4.2"
},
"scripts": {
"test": "jest"
}
}
// .babelrc
{
"presets": ["env", "react"]
}
// CheckboxWithLabel.js
import React from 'react';

export default class CheckboxWithLabel extends React.Component {
constructor(props) {
super(props);
this.state = {isChecked: false};
this.onChange = this.onChange.bind(this);
}

onChange() {
this.setState({isChecked: !this.state.isChecked});
}

render() {
return (
<label>
<input type="checkbox" checked={this.state.isChecked} onChange={this.onChange} />
{this.state.isChecked ? this.props.labelOn : this.props.labelOff}
</label>
);
}
}
// _tests__/checkbox_with_label.test.js
import React from 'react';
import {shallow} from 'enzyme';
import CheckboxWithLabel from '../CheckboxWithLabel';

it('CheckboxWithLabel changes the text after click', () => {
// Render a checkbox with label in the document
const checkbox = shallow(<CheckboxWithLabel labelOn="On" labelOff="Off" />);
expect(checkbox.text()).toEqual('Off');
checkbox.find('input').simulate('change');
expect(checkbox.text()).toEqual('On');
});

enzyme有三种渲染方式:

  1. shallow:Shallow Rendering (浅渲染)指的是,将一个组件渲染成虚拟DOM对象,但是只渲染第一层,不渲染所有子组件,所以处理速度非常快。它不需要DOM环境,因为根本没有加载进DOM。
  2. render:将React组件渲染成静态的HTML字符串,然后分析这段HTML代码的结构,返回一个对象。它跟shallow方法非常像,主要的不同是采用了第三方HTML解析库Cheerio,它返回的是一个Cheerio实例对象。
  3. mount:将React组件加载为真实DOM节点。

根据测试不同的内容,选取不同的渲染方式,比如测试组件第一层是否有某个类名,就只需要shallow,测试渲染了多少个子节点,就只需要render,而测试dom事件就需要使用mount

enzyme主要方法分为以下几类:

  • 选择器:enzyme有类似jquery的选择器方法,比如find、not
  • dom操作:html、get、hasClass、text、parents
  • 函数:some、filter、last、every、forEach、map
  • react: props、render、unmount、setState
  • 事件:simulate

react组件测试起来也会很方便。

坚持原创技术分享,您的支持将鼓励我继续创作!