乐趣区

单元测试

最近想给本人的 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 enzyme
yarn 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. 咱们学习到了配置, 以及语法示意的含意

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

退出移动版