最近想给本人的ui轮子写一个单元测试,为什么会这么想呢?因为它能涨工资呀,哈哈哈,当然咱们学习是不能那么功利的(放P,哈哈哈)
除了涨工资没别的了?当然不是,他是有它的益处的,否则学他干嘛
单元测试的益处是啥?
- 重构、重构、重构,重要的事件说三遍
TDD(测试驱动开发)的具体实现就是通过红灯->绿灯->重构一直反复,一步一步去强壮咱们的代码,保障今后重构代码的时候测试的精确,能够在重构中精确的定位到问题。同时也为当前的开发提供反对,在测试的根底上咱们能够重构构造和业务性能。 - 单元测试是最好的正文
测试会提醒你哪些步骤是能够通过、如何应用的最好文档。更具体的标准了测试指标的边界值与非法值。 - 定位bug,缩小bug
单元测试能够通过不同的条件来发现问题在哪里,在一些弱类型的语言中也防止了一些类型查看的低级谬误,当然这个当初咱们都用TypeScript做到了。 - 被迫的标准组织构造
可能平时咱们会把一个办法写的很简单、一个类写的很大,没有想过如何去组织构造,但如果你想到你行将的测试要如何写的时候,那可能你在开发前必须要想想哪些局部能够提出来了。这样会缓缓养成很好的思维。
好了,不多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", },
下面这段代码这里来解释一下:
- 测试时候,所有的jpg|jpeg|等等用
/test/__mocks__/file-mock.js
替换掉 - 测试时候,所有的(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,首先下载两个库enzyme
和enzyme-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被调用了,测试通过了
总结
- 这篇文章是自己在写Icon组件中,学习jest单元测试进行的配置,以及语法
- 咱们理解到了,单元测试的益处,为什么要学他....
- 咱们学习到了配置,以及语法示意的含意
这便是自己在学习过程中和大家的分享,一遍遍踩坑,一遍遍爬过去会有许多成长,置信大家也肯定有这种感触,一起致力吧!!!