1.react测试体验
1.1安装
create-react-app react-testcd react-test
1.2 创建sum.js
module.exports = function(a,b){ return a+b;}
1.3 创建sum.spec.js
let sum = require('./sum');it('a+b',function(){ expect(sum(1,2)).toBe(3);});
1.4 运行测试
npm test
2.enzyme测试
- Shallow Rendering(浅渲染)指的是,将一个组件渲染成虚拟DOM对象,但是只渲染第一层,不渲染所有子组件,所以处理速度非常快。它不需要DOM环境,因为根本没有加载进DOM
- find()方法:只支持简单选择器 类选择器、id选择器、标签选择器、复合选择器
2.1 安装enzyme
npm i enzyme enzyme-adapter-react-16 -D
2.2 创建 TodoInput.js
import React, { Component } from 'react';export default class TodoInput extends Component { handleKeyDown = (event) => { let code = event.keyCode; if (code == 13) { let text = event.target.value; this.props.addTodo(text); event.target.value = ''; } } addTodo = () => { let text = this.todo.value; this.props.addTodo(text); this.todo.value = ''; } render() { return ( <div> <input ref={input => this.todo = input} onKeyDown={this.handleKeyDown} /> <input id="addBtn" onClick={this.addTodo} defaultValue="增加" /> </div> ) }}
2.3 创建 TodoInput.spec.js
import React from 'react';import Enzyme,{shallow} from 'enzyme';import TodoInput from './TodoInput';import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({adapter:new Adapter()});//http://airbnb.io/enzyme/docs/api/ShallowWrapper/find.html//http://airbnb.io/enzyme/docs/api/selector.htmlit('shoud render 请输入',function(){ const wrapper = shallow(<TodoInput/>); const h3 = wrapper.find('h3'); const input = wrapper.find('input'); expect(h3.text()).toBe('待办事项'); expect(input.props().defaultValue).toBe('请输入');});
2.3 创建 TodoList.js
import React, { Component } from 'react';import TodoItem from './TodoItem';export default class TodoList extends Component { render() { return ( <ul> { this.props.todos.map(todo => <TodoItem key={todo.id} todo={todo} delTodo={this.props.delTodo} toggleTodo={this.props.toggleTodo} />) } </ul> ) }}
2.4 点击事件
import React from 'react';import Enzyme,{shallow} from 'enzyme';import TodoInput from './TodoInput';import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({adapter:new Adapter()});//http://airbnb.io/enzyme/docs/api/ShallowWrapper/find.html//http://airbnb.io/enzyme/docs/api/selector.htmldescribe('测试TodoInput',function(){ let todos; beforeEach(()=>{ todos =[{text:'1'},{text:'2'}]; }); it('shoud render 请输入',function(){ let wrapper = shallow(<TodoInput/>); const h3 = wrapper.find('h3'); const input = wrapper.find('input'); expect(h3.text()).toBe('待办事项'); expect(input.props().defaultValue).toBe('请输入'); }); it('点击按钮的时候调用addTodo方法',function(){ let addTodo = jest.fn(); let wrapper = shallow(<TodoInput addTodo = {addTodo}/>); let button = wrapper.find('button'); button.simulate('click'); expect(addTodo).toBeCalled(); });});
2.5 TDD
- TDD是测试驱动开发(Test-Driven Development)是敏捷开发中的一项核心实践和技术,也是一种设计方法论
- TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码
创建reducer.js
const ADD_TODO = 'ADD_TODO';const DEL_TODO = 'DEL_TODO';let INIT_STATE = [{id:1,text:'1'},{id:2,text:'2'}];function reducer(state=INIT_STATE,action={}){ switch(action.type){ case ADD_TODO: return [...state,action.todo]; case DEL_TODO: return state.filter(item=>item.id != action.id); default: return state; }}module.exports = reducer;
创建reducer.spec.js
let reducer = require('./reducer');const ADD_TODO = 'ADD_TODO';const DEL_TODO = 'DEL_TODO';describe('reducer',()=>{ let INIT_STATE = [{id:1,text:'1'},{id:2,text:'2'}]; it('初始状态',()=>{ expect(reducer(undefined,{})).toEqual(INIT_STATE); }); it('增加todo',()=>{ let todos = reducer(INIT_STATE,{type:ADD_TODO,todo:{id:3,text:'3'}}); expect(todos).toEqual([...INIT_STATE,{id:3,text:'3'}]); }); it('删除todo',()=>{ let todos = reducer(INIT_STATE,{type:DEL_TODO,id:2}); expect(todos).toEqual([{id:1,text:'1'}]); });});
2.6 测试点击事件
import React from 'react';import Enzyme,{shallow} from 'enzyme';import TodoItem from './TodoItem';import Adapter from 'enzyme-adapter-react-16'; import { wrap } from 'module';Enzyme.configure({adapter:new Adapter()});//http://airbnb.io/enzyme/docs/api/ShallowWrapper/find.html//http://airbnb.io/enzyme/docs/api/selector.htmldescribe('TodoItem',function(){ it('todo',()=>{ const wrapper = shallow(<TodoItem todo={{id:1,text:'1'}}/>); expect(wrapper.text()).toMatch(/1/); expect(wrapper.hasClass('todo')).toBe(true); expect(wrapper.hasClass('todo-selected')).toBe(false); }); it('todo-selected',()=>{ const wrapper = shallow(<TodoItem todo={{id:1,text:'1'}}/>); expect(wrapper.text()).toMatch(/1/); wrapper.simulate('click'); expect(wrapper.hasClass('todo')).toBe(false); expect(wrapper.hasClass('todo-selected')).toBe(true); });});
2.7 mount
mount将React组件加载为真实的DOM
- .get(index):返回指定位置的子组件的DOM节点
- .at(index):返回指定位置的子组件
- .text():返回当前组件的文本内容
- .html():返回当前组件的HTML代码形式
- .props():返回根组件的所有属性
- .prop(key):返回根组件的指定属性
- .state([key]):返回根组件的状态
import React from 'react';import Enzyme,{mount} from 'enzyme';import TodoApp from './TodoApp';import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({adapter:new Adapter()});describe('TodoApp',function(){ it('addTodo',()=>{ let wrapper = mount(<TodoApp/>); let len = wrapper.find('li').length; wrapper.find('button').at(0).simulate('click'); expect(wrapper.find('li').length).toBe(len + 1); }); it('delTodo',()=>{ let wrapper = mount(<TodoApp/>); let len = wrapper.find('li').length; wrapper.find('button').at(1).simulate('click'); expect(wrapper.find('li').length).toBe(len - 1); });});
3. 参考
- create-react-app
- jest
- expect
- jest中文网
- enzyme
- Jasmine
- istanbul
- prop-types