最近想给本人的ui轮子写一个单元测试,为什么会这么想呢?因为它能涨工资呀,哈哈哈,当然咱们学习是不能那么功利的(放P,哈哈哈)

除了涨工资没别的了?当然不是,他是有它的益处的,否则学他干嘛

单元测试的益处是啥?

  1. 重构、重构、重构,重要的事件说三遍
    TDD(测试驱动开发)的具体实现就是通过红灯->绿灯->重构一直反复,一步一步去强壮咱们的代码,保障今后重构代码的时候测试的精确,能够在重构中精确的定位到问题。同时也为当前的开发提供反对,在测试的根底上咱们能够重构构造和业务性能。
  2. 单元测试是最好的正文
    测试会提醒你哪些步骤是能够通过、如何应用的最好文档。更具体的标准了测试指标的边界值与非法值。
  3. 定位bug,缩小bug
    单元测试能够通过不同的条件来发现问题在哪里,在一些弱类型的语言中也防止了一些类型查看的低级谬误,当然这个当初咱们都用TypeScript做到了。
  4. 被迫的标准组织构造
    可能平时咱们会把一个办法写的很简单、一个类写的很大,没有想过如何去组织构造,但如果你想到你行将的测试要如何写的时候,那可能你在开发前必须要想想哪些局部能够提出来了。这样会缓缓养成很好的思维。

好了,不多BB,看看怎么用吧!!!

我用的是jest测试哦!!!

首先开始看一下我之前的配置,之前的文章有我的配置,防止你找的烦,我把配置放在这里https://github.com/sunkuangdo... 须要的请自行下载吧!

1.看一下我的jest.config.js中testMatch,通知我须要在lib文件夹中创立个目录__tests__,__tests__的目录外面xxxx.unit.(js|jsx|ts|tsx)这样的文件就是测试文件

那就创立个文件夹和文件呗

2.我要测试啥呢?我先测试我ui轮子外面的一个函数,试一下

这是我之前写的一个函数,就测试他,他会承受一个className


3.在classes.unit.jsx外面写一个,单元测试

// 先将测试文件导入进来import classes from "../helpers/classes";// 要在describe外面进行测试describe('classes', () => {  // it是申明,第一个参数是对测试的形容,第二个参数是函数,外面是对测试的执行  it('他承受 className', () => {    // 我给classes函数传了一个字符串a    const result = classes('a')    // 我断言result会是一个字符串a    expect(result).toEqual('a')  })})

4.哈哈哈,乐不可支的运行一下,如果你是yarn并且用的我得配置,就用yarn test
MMP,报错了,说我少了一个配置'babel-preset-react-app',装置一下呗

yarn add --dev babel-preset-react-app


5.装置胜利了,再来一下看看yarn test,哎,胜利,真香!

6.每次改写测试文件,都要我yarn test,好烦....,试试这个操作yarn test --watch,每次更改都会自动测试啦!
7.我要是想测试一个icon组件怎么办?来,咱们持续搞起来
看上面这段代码

import * as renderer from 'react-test-renderer'import React from "react";import Icon from '../icon'describe("icon",()=>{  it("ICON 是 SVG",()=>{    // 首先用renderer创立一个Icon,而后把Icon转成json    const json = renderer.create(<Icon/>).toJSON();    // 这个json进行快照    expect(json).toMatchSnapshot()  })})

8.当我运行到这里认为能够进行测试的时候,意外呈现了....bug了,起因是我测试的Icon组件中有用到scss没有配置,无奈辨认
首先在test目录下创立新的目录,并创立上面的两个文件

而后在file-mock.js中退出这段代码module.exports = 'test-file-stub';在object-mock.js中退出这段代码module.exports = {};
最外层找到jest.config.js文件,替换这段

moduleNameMapper: {        "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/__mocks__/file-mock.js",        "\\.(css|less|sass|scss)$": "<rootDir>/test/__mocks__/object-mock.js",    },

下面这段代码这里来解释一下:

  1. 测试时候,所有的jpg|jpeg|等等用/test/__mocks__/file-mock.js替换掉
  2. 测试时候,所有的(css|less|sass|scss)用/test/__mocks__/object-mock.js替换掉

9.哈哈哈,再跑一下,嗯.....,本认为解决了,唉!!!新问题呈现了,来源于这个文件的报错

嗯?我测试的时候也不须要测试svg啊,果决的删除console.log(error),这样子就不报错了
10.咱们来看一下这段代码expect(json).toMatchSnapshot(),他做了什么样的事件,咱们看一下.snap

<svg  className="fui-icon">  <use    xlinkHref="#undefined"  /></svg>

他会帮咱们生成一个svg,为什么use会是undefined???因为我还没有给他传name值,给name传递一个值,从新运行yarn test之后,报错了

他说咱们批改了内容,然而快照没有批改,与快照不同,这时候须要从新运行,批改快照外面的内容,从新运行yarn test -u意味着保留咱们最新的正确的快照

11.咱们来测试一下onClick,首先下载两个库enzymeenzyme-adapter-react-16,运行

yarn add --dev enzymeyarn add --dev enzyme-adapter-react-16

配置test目录下的setupTests.js文件

  const enzyme = require('enzyme')  const Adapter = require('enzyme-adapter-react-16')  enzyme.configure({adapter: new Adapter()})


接下来咱们onClick进行测试,一点一点看他表白了什么意思
咱们是要测试一个点击事件函数,导入了这个库之后,这个库帮咱们生成了一个假的页面,并将测试的函数传入Icon组件,找到svg模仿点击svg,咱们本人创立一个fn测试看看对不对,咱们期待n等于2,如果不确定是否测试胜利,将n改成1试一试

 import {mount} from 'enzyme'  describe("icon", () => {     it("onClick", () => {         let n = 1;         const fn = () => {             n = 2         }         // 生成假想页面         const comonent = mount(<Icon name="baidu" onClick={fn}/>)         // 找到svg模仿点击svg         comonent.find('svg').simulate('click')         // 咱们期待n等于2         expect(n).toEqual(2)     }) })

然而咱们这个办法有点笨,每次测试都要本人写个fn,傻乎乎的!!!
能不能让jest帮咱们写一个fn呢
const fn = jest.fn();这段代码是让jest创立一个fn()
expect(fn).toBeCalled();咱们期待fn会被调用

  it("onClick", () => {      const fn = jest.fn();      const component = mount(<Icon name="baidu" onClick={fn}/>)      component.find('svg').simulate('click')      expect(fn).toBeCalled();  })

运行yarn test,测试通过了,然而咱们不晓得是不是真的进行测试了,创立一个fn2,这个fn2咱们并不会传,看看报错了没有,报错了,就是真的测试了,阐明onClick被调用了,测试通过了

总结


  1. 这篇文章是自己在写Icon组件中,学习jest单元测试进行的配置,以及语法
  2. 咱们理解到了,单元测试的益处,为什么要学他....
  3. 咱们学习到了配置,以及语法示意的含意

这便是自己在学习过程中和大家的分享,一遍遍踩坑,一遍遍爬过去会有许多成长,置信大家也肯定有这种感触,一起致力吧!!!