在一个多人协做的大型项目中,咱们在开发的过程当中可能常常会面临到这样的问题:css
当咱们被提出这些bug的时候,咱们是二脸懵逼的,由于这不符合一个程序员的预期!!!
那么咱们如何可以避免以上的问题,从而将经历投入到更多的开发(写bug)中去呢?
笔者在这里试着概括了一下解决问题的办法html
(推荐)前端
.app{
width: 100%;
.center{
height: 100%
}
}复制代码
(不推荐)react
.app{
width: 100%;
}
.center{
height: 100%
}复制代码
其实以前就已经简单的了解过了单元测试,但当时对于单元测试我是持有一种很否认的态度的,由于他太过于鸡肋,都是测试一些很基础的功能,可是当笔者被此次重构折磨以后,有从新思考了下如何可以保证代码的健壮性,抱着这个态度,笔者又去调研了下单元测试到底可以作什么。ios
从字面解析来看,那就是把你的代码,拆分红一个一个的单元,而后针对不一样的单元,编写不一样的测试用例。git
那这时候咱们就会有一个问题了,那若是单元测试经过了,那到底能不能就不须要测试同窗再测试就直接上线了呢?程序员
按照咱们的理想状况,若是咱们的测试用例覆盖率达到了5个9以上,那应该是能够直接发布了,可是这个时候其实咱们的心里仍是会有一些疑虑,就是,那一个一个的模块都已经经过了,那集成在一块儿会不会有问题呢?这其实也是笔者到如今还不肯定的问题。(获取集成测试可以解决?若是你已经有了答案,欢迎下方指正)github
基于此,笔者但愿在前端编写测试用例可以实现如下的目标:json
本着实现以上的要求,笔者下来介绍下具体的使用,关于不一样测试框架的重点,这篇文章就不详细展开了,最终结合咱们的项目,最终采用了facebook的jest+enzyme。重点将展开如下两种react组件类型测试。redux
展现型组件测试,意思就是要确保每一次的修改都是符合预期的,这里笔者要着重介绍下jest框架里面的snapshot功能。
shapshot就是会对组件进行一次快照记录当前的状态,每一次run jest的时候,对比上一次,看看是否有变化。那最完美的状况就是,咱们将全部的css样式打包,而后渲染出组件ui,对比上一次的纪录,看看是否有修改,可是很惋惜,目前shapshot生成的快照文件里面只有class,并无相关样式,除非你把全部样式写成style内联,那么他就能记录下你的style样式。看似好像没有达到咱们的目标。
可是仔细想一想,这其实就违背了咱们单元测试的初衷,笔者这里也大胆猜想下,jest官方在实现这个功能的时候,应该也只是想记录下一步一步的事件后,当前组件的html结构,对比上一次的快照,来看功能是否符合预期。代码的话比较简单:
describe('XJLayerCard', () => {
it('renders correctly', () => {
const wrapper = Enzyme.render(<XJLayerCard {...mockData}/>);
expect(toJson(wrapper)).toMatchSnapshot();
})
})复制代码
功能性组件测试,就是要覆盖到一个组件的基础功能,可以确保每个修改以后,跑完单元测试,可以肯定以前的功能正常。
一开始我以为单元测试很鸡肋的缘由也是没有深刻了解它,此次发现就算是和业务结合很紧密的组件,也可以模拟正常的操做,这里就贴一个和redux结合的组件来举例
import React from 'react';
import Enzyme from 'enzyme';
import AppInput from '../AppInput';
import toJson from 'enzyme-to-json'
import initialStore from '@/../__mocks__/store.js';
import appInfoData from '@/../__mocks__/appInfo.js'
import { Provider } from 'react-redux';
import configureStore from '@/entries/maker/redux/store';
import { updateAppInfo } from '@/entries/maker/redux/action';
import moxios from 'moxios';
import instance from '@/api/instance'
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
let store;
let wrapper;
beforeEach(() => {
moxios.install(instance);
store = configureStore(initialStore)
wrapper = Enzyme.mount(
<Provider store={store}>
<AppInput onChange={(obj) => {
store.dispatch(updateAppInfo(obj))
}}/>
</Provider>
)
})
afterEach(function () {
moxios.uninstall(instance);
})
describe('demo', () => {
it('renders correctly', () => {
expect(toJson(wrapper)).toMatchSnapshot();
});
it('click div, select show', () => {
// 渲染选项框正常
expect(wrapper.find('.xj-appinput-item').length).toEqual(2);
// 一开始没有输入框
expect(wrapper.find('input').length).toEqual(0);
wrapper.find('.xj-appinput-value-wrapper').at(0).simulate('click');
expect(wrapper.find('input').length).toEqual(1);
});
it('updateAppInfo action', (done) => {
// 拦截请求
moxios.stubRequest('/app/get', {
status: 200,
responseText: 'success'
});
// 点击下拉框中的第一个,会触发action
wrapper.find('.xj-appinput-item').at(0).simulate('click');
moxios.wait(() => {
// mock数据
let request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: appInfoData
}).then((res) => {
// input输入框消失
expect(wrapper.find('input').length).toEqual(0);
// 选中的app展现出来
expect(wrapper.find('.xj-appinput-wrapper').length).toEqual(1);
expect(toJson(wrapper)).toMatchSnapshot();
done();
}).catch(err => {
console.log(err)
})
});
})
})复制代码
能够看到,这里的测试内容是结合了redux,axios库。那其实整个流程就是初始化这个组件,看看渲染的html结构是否符合预期,而后点击下拉框,选中其中第一个,发起请求,拉回详细数据,再观察组件是否展现正常,编写完测试用例后,就已经用代码模拟了整个手工操做,怎么样,是否是很强大?
以为有点帮助的,去点个star吧