在一個多人協做的大型項目中,咱們在開發的過程當中可能常常會面臨到這樣的問題: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吧