Jest、Enzyme 简介
Jest 是 Facebook 宣布的一个开源的、基于 Jasmine 框架的 JavaScript 单元测试东西。
Enzyme 是 React 的测试类库。 Enzyme 供应了一套简约壮大的 API,并经由过程 jQuery 作风的体式格局举行DOM 处置惩罚,开辟体验异常友爱。
一般要领测试
起首,运用npm
装置Jest
npm install --save-dev jest
在目录下新建一个待测试文件 sort.js
。
function sort(sortArr) {
return sortArr.sort((a, b) => a - b);
}
module.exports = sort;
此处sort要领未对入参做范例检测
在这里定义了一个数组排序要领,下面来誊写其测试用例,在目录下新建一个sort.test.js
文件。
const sort = require('./sort');
const arr = [5,2,4,3,1];
test('排序数组[5,2,4,3,1]', () => {
expect(sort(arr)).toEqual([1,2,3,4,5]);
})
在用例中,我们先引入了待测试的要领,接下来定义了一个排序数组[5,2,4,3,1]的测试用例.test()
用来定义一个测试用例,expect()
会实行内部的要领,返回一个待测试的效果。toEqual()
用来推断返回的效果于希冀的效果是不是相称。这里由于希冀返回效果为数组,所以运用toEqual
举行推断,除此以外,另有toBe()
,toBeNull()
等要领来比较差别的范例。更多内容…
翻开package.json
,在scripts
中新增
test: "jest"
然后运转敕令
npm run test
会看到用例测试经由过程的信息
由于我们的要领没有做入参范例检测,下面经由过程传入字符串,来测试异常情况。在sort.test.js
中新增一个测试用例用例
test('排序字符串“52431”', () => {
expect(sort('52431')).toEqual(12345);
})
运转,则会看到测试失利的信息
从测试效果中我们能够消灭的看到,运转来两个测试用例,第一个用例经由过程来,第二个用例运转是js涌现了报错。此时便能依据测试效果,调解代码
更多测试要领此处不做议论,详细能够参考Jest文档
在详细项目中的运用
下面来在现实的项目中运用Jest + Enzyme来举行测试。测试Demo项目
起首,运用Create-React-App
来建立一个运用。
接着,装置jest
npm install --save-dev jest
由于在誊写用例时,会用到es6语法,所以还要装置babel-jest
来举行转码
npm install --save-dev babel-jest
装置enzyme
npm install --save-dev enzyme
也能够运用react官方测试插件react-addons-test-utils
,此处我们运用enzyme,故不须要装置。
别的,还须要依据运用的react版本来装置enzyme-adapter-react
。详细版本对比以下
enzyme-adapter-react版本 | react版本 | ||
---|---|---|---|
enzyme-adapter-react-16 | ^16.4.0-0 | ||
enzyme-adapter-react-16.3 | ~16.3.0-0 | ||
enzyme-adapter-react-16.2 | ~16.2 | ||
enzyme-adapter-react-16.1 | `~16.0.0-0 \ | \ | ~16.1` |
enzyme-adapter-react-15 | ^15.5.0 | ||
enzyme-adapter-react-15.4 | 15.0.0-0 - 15.4.x | ||
enzyme-adapter-react-14 | ^0.14.0 | ||
enzyme-adapter-react-13 | ^0.13.0 |
此处demo运用的react
版本为^16.4.1
,所以我们须要装置enzyme-adapter-react-16
npm install --save-dev enzyme-adapter-react-16
依靠装置完成,接下来须要举行相干的设置。
起首设置package.json的测试敕令test: "jest"
。
此时假如我们在根目录下建立一个.test.js
文件,并誊写简朴的要领用例,实行测试敕令,是能够一般实行测试用例的。然则,我们的项目却并非简朴的单个要领但测试,现实项目中会存在这大批的组件依靠,另有css
,image
等静态资本的处置惩罚。所以,还要举行以下设置处置惩罚。
起首,我们在package.json
文件中新增一个jest
的设置项
jest: {}
这里我们重要举行三个设置。
-
moduleFileExtensions
代表支撑加载的文件名。此处我们的测试文件均以.js
末端,所以只设置成["js"]
即可 -
transform
用于编译 ES6/ES7 语法,需合营 babel-jest 运用 -
moduleNameMapper
代表须要被 Mock 的资本称号。假如须要 Mock 静态资本(如less、scss等),则须要设置 Mock 的途径
jest默许会检索项目内的*.test.js
,*.test.jsx
情势的文件并实行。当编写当用例没被jest检索到时,可经由过程moduleDirectories
来设置途径。
在详细到组件测试时,为了测试组件到交互性,我们须要jest衬着出组件举行操纵,此时,由于我们到项目中大批运用来webpack
到依靠治理,以及less-loader
、url-loader
等预编译。在jest衬着组件是,没法辨认这些.less
等文件。所以我们须要经由过程mock
来处置惩罚这些静态文件。由于jest在衬着组件时,是不须要依靠css
,image
等静态资本的。所以我们能够如许设置:
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
前面经由过程正则来适配我们须要婚配的静态文件,背面为我们经由过程mock返回的数据。这里我们还须要在根目录中建立__mock__
的文件夹。在里面新建fileMock.js
和styleMock.js
两个文件。
<!--fileMock.js-->
module.exports = 'test-file-stub';
<!--styleMock.js-->
module.exports = {};
如许就能够将测试集合在组件的构造和逻辑上。别的,可能在我们的项目中,会运用大批的别号来简化援用途径,及webpack中的alias
设置。此处一样须要举行别号的设置,设置体式格局与静态资本设置相似。一下是完全设置
"jest": {
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"src",
"node_modules"
],
"transform": {
"^.+\\.js$": "babel-jest"
},
"moduleNameMapper": {
"^components(.*)$": "<rootDir>/src/components$1",
"^pages(.*)$": "<rootDir>/src/pages$1",
"^utils(.*)$": "<rootDir>/src/utils$1",
"^services(.*)$": "<rootDir>/src/services$1",
"^static(.*)$": "<rootDir>/src/static$1",
"^models(.*)$": "<rootDir>/src/models$1",
"^variable(.*)$": "<rootDir>//src/static/less/variable.less",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
}
}
接下来建立一个待测试的组件,在src > pages
文件夹中建立login
组件,并设置好路由。组件代码参考测试Demo项目
运转后页面以下
<img src=”https://github.com/ISummerRai…; width=”320″ />
接着,定义测试用例,此Demo定义来八个测试用例以下
- 1、页面title显现“登录”(UI)
- 2、登录账号输入手机号或邮箱时,账号上方显现登录账号
- 3、登录账号输入不为手机号或邮箱,账号上方显现【账户输入毛病,请从新输入】
- 4、账号输入一般,暗码小于6位,登录按钮置灰。
- 5、账号输入异常,暗码不小于6位,登录按钮置灰。
- 6、账号输入一般,暗码不小于6位,登录按钮可点。
- 7、点击暗码后眼睛图标,显现暗码。
- 8、显现暗码状况,再次点击,隐蔽暗码。
接下来,新建文件login.test.js
来编写测试用例代码。
由于用例中设想多个交互,所以我们须要先衬着出组件。Enzyme为我们供应来三种衬着组件的要领shallow
、render
、mount
。
-
shallow
要领就是官方的shallow rendering的封装。 -
render
要领将React组件衬着成静态的HTML字符串,然后剖析这段HTML代码的构造,返回一个对象。它跟shallow要领异常像,重要的差别是采用了第三方HTML剖析库Cheerio,它返回的是一个Cheerio实例对象。 -
mount
要领用于将React组件加载为实在DOM节点。
三种要领中,shallow
render
返回的为对象,用于剖析HTML构造,所以没法用于交互测试。mount
要领加载的为实在的DOM节点,所以可用于交互测试。本Login
组件存在大批交互测试,所以运用mount
建立组件,运用mount
须要先运用Adapter
设置以下
import Login from 'pages/Login';
import React from 'react';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { mount } from 'enzyme';
configure({ adapter: new Adapter() });
const wrapper = mount(<Login />);
如今,我们就能够运用Enzyme
的API来编写测试用例了,Enzyme
供应了雄厚的类jquery
作风的API,下面是部份API
.get(index):返回指定位置的子组件的DOM节点
.at(index):返回指定位置的子组件
.first():返回第一个子组件
.last():返回末了一个子组件
.type():返回当前组件的范例
.text():返回当前组件的文本内容
.html():返回当前组件的HTML代码情势
.props():返回根组件的一切属性
.prop(key):返回根组件的指定属性
.state([key]):返回根组件的状况
.setState(nextState):设置根组件的状况
.setProps(nextProps):设置根组件的属性
完全API拜见 Enzyme API
在前半部份的demo中,我们运用来 test()
要领来编写用例,此处,我们运用
describe('', () => {
it('', () => {})
})
来编写测试用例,如许我们能够对测试用例举行分组
让我们来最先第一个用例“页面title显现「登录」”的编写
it('题目显现', () => {
const title = wrapper.find('.title').text();
expect(title).toBe('登录');
})
这个用例异常简朴,仅仅在第一步猎取到了title
中的文本,并对文本举行校验。
第二个和第三个用例为对输入框输入文本对校验,此处,我们能够零丁对校验要领举行测试,也能够页面临交互来完成测试。这里用例经由过程交互来举行测试用例对编写。由于在输入信息过程当中,校验经由过程input
框的onChange
事宜触发,所以我们须要用到 simulate
来触发事宜。个中一个用例以下
const accountInput = wrapper.find('.account').find('input');
const accountTitle = wrapper.find('.account .name').find('span');
it('输入不合法账号', () => {
const event = {
target: {
value: 'abc123'
}
}
accountInput.simulate('change', event);
expect(accountTitle.text()).toBe('账户输入毛病,请从新输入');
})
模仿输入来一个不合法的账号‘abc123’,考证失利,显现失利信息。
在4,5,6三个用例中,须要猎取登录按钮Button
组件的可点击状况,由于enzyme
没法猎取 css
状况,此时能够运用API中的prop(key)
来猎取组件的props状况,从而推断组件的可点击状况。个中一个用例以下
it('输入准确账号,暗码小于6位,指定状况', () => {
wrapper.setState({
account: '18888888888',
password: '12345',
errorAccount: false
});
// 此处需从新猎取btn对象,否则会导致用例失利
const submitBtn = wrapper.find('.btn-box').find('Button');
expect(submitBtn.props().disabled).toBe(true);
})
此处经由过程直接设置state
的值来变动Button的状况。须要注重的是,为来削减反复定义,很多Dom对象的猎取都在describe
组下做了一致的定义,但在实行expect
猎取按钮状况是,须要从新查找,来猎取最新但状况。除了直接指定state
状况以外,还能够经由过程输入框输入,change事宜触发但体式格局来完成用例,以下
it('输入准确账号,暗码小于6位,经由过程change触发', () => {
const accountEvent = {
target: {
value: '18888888888'
}
};
const pwdEvent = {
target: {
value: '12345'
}
}
accountInput.simulate('change', accountEvent);
passwordInput.simulate('change', pwdEvent);
const submitBtn = wrapper.find('.btn-box').find('Button');
expect(submitBtn.prop('disabled')).toBe(true);
7、8两个用例运用但要领与上面雷同,不再赘述。
一切用例编写完成以后,实行npm run test
能够看到一切用例都经由过程测试。
测试覆蓋率
在 package.json
文件的 test
敕令修改成
test: "jest --coverage"
实行 npm run test
即可在用例实行信息后显现用例的覆蓋率报告。