单元测试从零开始,包含 Vue 及 React 项目中该如何单测

前言

本文取自笔者的开源项目 前端进阶之路javascript

有兴趣的能够了解一下,目前还在写做中。css

正文

在这部分的内容中,你将学习到如下几点:html

  • 单元测试的做用
  • 最应该对哪些模块进行单元测试
  • React 和 Vue 这两大框架的单元测试学习路径
  • 如何在 React 和 Vue 这两大框架中进行单元测试以及 Demo 实战

单元测试是用来测试程序中一小块功能的,好比说一个函数、一个类。它能很显著地提升项目的代码质量,下降出现 Bug 的频率,而且也利于维护代码。前端

可是实际状况是绝大部分开发者是不肯意作这件事情的。由于平时开发都忙不过来,哪还有时间去作这些事情。vue

我我的其实认为业务代码的测试应该是不强求的,毕竟需求常常在变化。若是对业务代码进行高覆盖率的测试,那么一旦需求变更就须要同步修改测试用例。这样编码的压力是双份的,极可能达不到快节奏上线的目的。java

可是对于依赖的基础组件库以及公共函数是必定须要编写单元测试的。由于这些内容会被多个模块使用到,而且也不会频繁变动这些基础的功能,编写单元测试的收益相对来讲高得多。就好比各类知名的开源项目的测试覆盖率每每是高于 90% 的,测试覆盖率低或者压根不写测试的开源项目通常不多直接用于项目中。node

那么咱们如何学习这方面的内容呢?首先不管你使用什么技术栈,都须要先选择一个测试框架。Jest 是其中一个相对来讲优秀的框架(不少知名开源项目也都在使用它),开箱即用,内部集成了断言库、Mock、快照功能等等。固然你也能够一样选择别的框架,核心内容都是同样的,无非 API 有所改变罢了。react

Jest 入门

Jest 总归是个使用起来很简单的框架,不须要太多的学习时间就能上手了。另外若是你想学习如何用好这个框架,最好的办法实际上是阅读工具库以及组件库的测试用例。git

如下是对 Jest 一些重要功能的简单介绍。github

断言

在 Jest 中使用最多的就是内部的断言库了,由于咱们须要用它来测试函数的输出是否与咱们预期的一致。

它的用法也很简单,你稍微会点英文就能看懂一段测试代码的用途,甚至于不须要去翻阅文档。好比说你指望一个函数的输出为 2

// 翻译出来就是我测试一段代码,指望函数(输入)等于我指望的输出
test('测试 1 + 1 = 2', () => {
  expect(sum(1, 1)).toBe(2)
})
复制代码

关于这部分的内容你们只须要翻阅下文档就能熟练使用了。

异步代码测试

异步获取数据确定是一个常见场景了。异步代码一般会有两种写法,分别为:

  • 回调函数
  • 函数返回 promise

在测试异步代码的时候,一般返回的数据是不肯定的,所以咱们只须要测试异步代码是否正常返回数据便可。

// 回调函数的写法,经过 done 来让测试代码一直等待
test('fetch success', done => {
  fetch(data => {
    expect(data.success).toBe(true)
    done()
  })
})
// 函数返回 promise 的写法,注意要加上 return
// 固然对于返回 promise 的函数咱们也能够直接使用 await
test('fetch success', () => {
  return fetch().then(data => {
    expect(data.success).toBe(true)
  })
})
复制代码

Mock 函数

假设咱们须要测试一个回调函数是否被执行、参数或者返回值是否正确,这时候咱们就可使用 Mock 函数。

function foo(cb) {
  cb(1)
}
const mockCallback = jest.fn(value => value + 1)
// 回调被调用
expect(mockCallback).toBeCalled()
// 回调函数参数为 1
expect(mockCallback.mock.calls[0][0]).toBe(1)
// 回调函数返回值为 2
expect(mockCallback.mock.results[0].value).toBe(2)
复制代码

固然 Mock 函数还有更多用法。好比模拟返回值,追踪函数被调用的各类状况等等,更多的内容能够阅读文档去学习。

快照

快照在测试组件时是个颇有用的功能,能够帮助咱们确保在维护代码的过程当中不会对组件的 UI 进行改变。

用法至关简单:

expect(组件实例).toMatchSnapshot()
复制代码

以上代码在第一次执行时会生成快照,在接下来的测试中每次都会去对比二者的内容是否一致。

配置文件

Jest 和 Babel 同样,使用的时候都须要一个配置文件。对于 Jest 来讲,你须要在根目录中建立一个名为 jest.config.js 的文件。

如下是一些常见的配置选项:

module.exports = {
  // 文件后缀
  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
  // 文件如何转换
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub',
    '^.+\\.jsx?$': 'babel-jest'
  },
  // 忽略的文件
  transformIgnorePatterns: ['/node_modules/'],
  // 生成快照须要的插件
  snapshotSerializers: ['jest-serializer-vue'],
  // 须要执行哪些目录下的测试用例
  testMatch: [
    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
  ],
  // 在执行用例前的配置文件
  setupFiles: ['./tests/setup.js'],
  // 测试覆盖率配置
  collectCoverage: true,
  coverageReporters: ['html', 'lcov', 'text-summary'],
  coverageDirectory: './test/coverage',
  collectCoverageFrom: ['components/**/*.vue']
}
复制代码

更多的配置属性能够查阅文档学习。

怎么对工具函数进行单测

对于工具函数来讲,首要一点就是这个函数不能包含太多的功能,拆分红一个个功能函数是最佳的方式,由于这样测试起来会很方便。

另外对于工具函数来讲,输出应该是可控的,因此写单测起来很容易,只须要 except 函数的输出便可。

怎么对组件进行单测

对于组件来讲,最重要的是为组件生成各个状态下的快照,以防代码变更后引起 UI 层面的 Bug。剩余的内容就是对各个功能进行测试了,好比说值设置的对不对啦、事件有没有响应啦、逻辑是否是正确啦等等,这部分的测试主要还要看具体组件的功能了。

另外若是你有作统计测试覆盖率的话,会发现 Branch 指标的提高每每是最难的对于组件来讲。一旦你能把这个指标提高到 95% 以上,那么这个组件的问题会少不少。

Vue 中实践 Jest

推荐在完成环境配置后阅读该文档

本小结 demo 地址

配置

无论你是现有项目仍是新项目须要使用 Jest,均可以经过 Vue Cli 3 解决。

对于现有项目,只须要在项目文件夹中执行一条命令便可

vue add unit-jest
复制代码

脚手架会自动在项目中帮你安装 Jest 须要的配置,安装完成后你会发现根目录中新增了一个文件夹

文件夹中包含了一个测试用例,你只需执行 yarn test:unit 便可运行测试用例。

对于新项目来讲,在建立项目过程当中须要选择 Manually select features,而后按照如下内容选择便可集成 Jest 环境。

实践

完成环境配置之后咱们就开始进行一个简单的组件测试吧。

PS:组件测试须要用到 @vue/test-utils 这个库,由于须要它来帮助咱们 mount 组件以及对组件进行一系列的操做。当组件挂载之后,咱们就能够经过 Jest 进行断言、Mock、生成快照等等。

在 components 文件夹下咱们新增一个 loading.vue 文件

<template>
  <div class="loading"> <span class="loading__indicator" :style="style" /> <span class="loading__text" v-show="text">{{ text }}</span> </div>
</template>

<script> export default { props: { text: String, size: { type: Number, default: 26 }, indicatorColor: { type: String, default: "#1989FA" } }, computed: { style() { return { width: this.size + "px", height: this.size + "px", borderColor: this.indicatorColor, borderBottomColor: "transparent" }; } } }; </script>
复制代码

以上代码是一个很简单的组件,传入 props 就完成了整个组件的渲染,没有其余的逻辑了。

测试用例也很简单,完成对全部的 props 输入输出对比便可实现 100% 的测试覆盖率。

describe('Loading.vue', () => {
  it('renders props.msg when passed', () => {
    const wrapper = mount(Loading, {
      propsData: {
        text: 'Loading',
        indicatorColor: 'red',
        size: 20
      }
    })
    const indicatorStyle = wrapper.find('.loading__indicator').element.style
    expect(wrapper.find('.loading__text').text()).toBe('Loading')
    expect(indicatorStyle.borderColor).toContain('red')
    expect(indicatorStyle.width).toContain('20px')
  })
  it('snapshot', () => {
    const wrapper = mount(Loading, {
      propsData: {
        text: 'Loading',
        indicatorColor: 'red',
        size: 20
      }
    })
    expect(wrapper).toMatchSnapshot()
  })
})
复制代码

执行 yarn test:unit 命令后,咱们应该能见到以下图的内容

若是你想更进一步学习在 Vue 中进行单元测试的内容,推荐如下资料:

React 中实践 Jest

推荐在完成环境配置后阅读该文档

本小结 demo 地址

配置

对于新项目来讲,若是你使用 create-react-app 的话,那么默认 Jest 就集成在内部了,你只须要运行命令 yarn eject 就能够在 package.json 文件中看到 Jest 的配置。

对于现有项目来讲,你能够经过个人 demo 或者这篇文章来学习相关的配置,这里就再也不赘述了。

另外可能有些同窗是 TS 的环境,所以个人 Demo 中是以 TS 为基础配置的。

实践

PS:组件测试须要用到 enzyme 以及 enzyme-adapter-react-16 这两个库,由于须要它们来帮助咱们 mount 组件以及对组件进行一系列的操做。当组件挂载之后,咱们就能够经过 Jest 进行断言、Mock、生成快照等等。

另外鉴于组件测试这块的内容基本和 Vue 中的一致,所以这里就不浪费篇幅复制代码了,具体内容能够去 demo 中学习。

若是你想更进一步学习在 React 中进行单元测试的内容,推荐如下资料:

总结

总的来讲在项目中进行单元测试须要学习的内容并很少,一个 Jest 外加一个可以挂载组件的库便可,一天既能上手这块的内容。

真正须要花时间学习的应该仍是阅读优秀第三方库的测试用例上。

相关文章
相关标签/搜索