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