关于单元测试,咱们须要知道什么?- 实践篇 - 偏方法论层面

实践篇

前言

本篇并不是完整指导读者如何进行单元测试,可是会结合部分例子讲解如何编写测试代码,从而引起读者自行思考,而后会给出编写单元测试途中建议。javascript

普通函数

举个例子,咱们本身写了一个校验密码格式(同时知足数字大小写字母)的函数以下:html

function isRightPassWord(password) {
  const pattern = new RegExp(/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])[a-zA-Z0-9]{8,16}$/);
  const isMatched = pattern.test(password);
  if (!isMatched) {
    return false;
  }
  return true;
}
复制代码

那问题来了,咱们如何去进行测试呢?若咱们并无写过任何的单元测验,其实很难下手,咱们并不清楚测试点在哪里?那咱们一块儿思考几个问题吧。vue

你测试的是什么?

这部分咱们要描述好,咱们对应测试的函数是什么,转化成代码就以下:java

describe('isRightPassWord function', () => {});
复制代码

Ta 是来作什么?

这部分咱们须要想一想,该函数的做用究竟是什么,已经想一想对应的边际状况。因此该函数是帮助咱们校验字符串是否同时知足数字大小写字母的,想到一个如传空的边际状况,如上思路转成代码,就是以下:react

test('with empty params', () => {});

test('with wrong params Aasdfxzs', () => {});

test('with correct params 123aAbBCc', () => {});
复制代码

Ta 实际输出什么?预期输出什么?

这部分咱们须要讲对应的上述条件的参数传入被测函数,断言对应的预期输出,而后运行程序,查看实际输出是否知足咱们预期,转化成对应的代码段,就是以下:git

// with empty params
expect(isRightPassWord()).toBe(false);
// with wrong params Aasdfxzs
expect(isRightPassWord('Aasdfxzs')).toBe(false);
// with correct params 123aAbBCc
expect(isRightPassWord('123aAbBCc')).toBe(true);
复制代码

最后一步,运行程序查看实际输出是否符合咱们的预期,而后继续书写其余测试代码,以后即是红绿灯游戏了。github

有一个问题,按照上文思路咱们是在函数完成后,进行补充对应的单测。过程实际体验上和直接在业务层使用并无什么差异,只是帮助咱们后续维护对应模块有了一层保障机制。api

可是可否先写好对应的测试,而后根据测试在驱动咱们编写对应的函数呢?这就是TDD概念。其实这样更符合咱们的编写代码习惯,只是将部分前置条件转化为对应的测试代码。app

解释一下,在编写代码以前会思考对应的需求,更可能是实现部分是如何实现该需求,而后边在业务逻辑层使用,边修改对应的代码段,然则这样循环机制中跳出的条件,直观的是知足了直接需求条件,但部分边界条件或许在需求测试期间被发现,而后从新开启循环机制,而跳出的条件就是修复对应问题并知足直接条件。框架

咱们一块儿优化对应的流程,起点咱们会思考对应的需求,将其拆解出若干个问题。如何对应的直接需求?对应的边际状况有哪些?而后根据对应的问题,进行书写测试代码,完成后运行测试,开始根据红绿灯游戏进行编写功能。

这时候你应该会有一个问题,这样作会形成时长大量增多吧?固然,其实思考的时候二者是差很少的,或是只是多了一步将思考转化成对应测试的步骤。那咱们的问题简化为如何减小书写测试的时间?多写,提取对应的模型,加入编辑器的 live Template 中。

结合 Vue

推荐官方教程,结合澳大利亚小哥的指南进行食用。若使用的CLI建立,可借鉴此文

借用Edd Yerburgh文中的一个例子,改写以下:

// src/components/Foo.vue
<template>
  <div class="foo">
    <button id="change-message" @click="changeMessage">Change message</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      msg: 'Welcome to Your Vue.js App'
    };
  },
  methods: {
    changeMessage() {
      this.msg = 'new message'
    }
  }
}
</script>
复制代码

注意:你须要根据官网去安装一堆的依赖包,而后如果自建项目,你须要处理好 Webpack 对应的loader问题。

// src/components/Foo.spec.js

import { expect } from 'chai'
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'

describe('Foo.vue', () => {
  it('changes h1 text when #change-text is clicked', () => {
    const wrapper = mount(Foo)
    const changeMessage = wrapper.find('#change-message')
    changeMessage.trigger('click')
    const h1 = wrapper.find('h1')
    expect(h1.text()).to.equal('new message')
  })
})
复制代码

@vue/test-utils提供了对应的函数,在测试环境实现了不一样的挂载方式,或是你不清楚挂载方式的区别,请查看对应的官网,或是React单元测试笔记中的部分概念。官网也总结了对应的经常使用技巧

结合 React

很久没主要写过了 React 测试相关代码,因此就不一一赘述对应的思路以及流程,毕竟单测方式是同样的。查看了对应官网是有提供对应的测试依赖的。但我记得通常都是测试框架使用Jest + EnzymeEnzyme@vue/test-utils包裹组件,而后暴露出来的接口使用习惯仍是和jQuery的使用习惯差很少的。

如何实践?

还记得引言篇的问题吗?

你是否信任你写的代码吗?

你如何检测代码质量?

你如何验证你的记性?

将单测加入咱们实践中,确实存在不少阻力,其做用是长远的。不只帮助咱们细化自身处理方式,还帮助咱们引起自身的思考。如何将函数/函数抽离的更符合单一原则?如何区分功能界限?单测要不要强调覆盖率?

参考文献

  1. Vue 官方教程
  2. 【译】每一个单元测试必须回答的 5 个问题
  3. Five Traps to Avoid While Unit Testing Vue.js
  4. How to unit test Vue components for beginners
  5. Vue testing handbook
相关文章
相关标签/搜索