前端单元测试学习 unit-testing

1,325 阅读5分钟

单元测试学习记录

开头狗头警告~哈哈

目前自己所在公司规模不大,还是外包性质的,所以项目众多,每天都疲于业务之间,最近忙里偷闲,觉得咱们做技术的虽然是服务于业务,但是也不能一直被业务支配,还是不能忘记提升自己的技术,自身技术才是核心竞争力。很多新技术,可能在一些小项目上用不到,甚至在一些新技术的使用方面,很多人会有很多顾虑,但是我始终觉得,技术没有高低贵贱,如果有,那肯定是使用者的问题。

哈哈哈,逼逼赖赖了这么多,咱们进入正题吧

单元测试概念

对最小的可测试单元进行自动化测试 ---(个人理解就是对方法进行测试)

  • 分模块开发,方便地定位到那个单元出来问题
  • 保证代码质量
  • 驱动开发

第一点和第二点都比较好理解,讲到第三点,就需要讲两个概念了:TDD 和 BDD

TDD

  • 需求分析 --> 编写单元测试 --> 编写代码使单元测试通过 -->重构

BDD

  • 从业务角度定义目标 --> 找到实现目标的方法 --> 编写单元测试 --> 实现行为 --> 检查产品

单元测试的原则

  • 及时修改和维护
  • Code review
  • 只测单一的点
  • 尽量贴近真实
  • 避免测试中逻辑过于复杂

现状

比如我公司现在的开发流程就是以 BDD 开发流程为主,先需求分析,然后编写技术实现文档,审核完后 开发er 开始开发需求,测试er 开始写自己的测试用例(两边并发执行),开发完成之后,开始进行测试。这样的过程符合一般人们的逻辑,但是看了 TDD 之后,有一种耳目一新的感觉,隐约觉得 TDD 更为合理。(但是想要走TDD流程,那针对公司现有开发流程需要改进的地方就太多了,慢慢来吧)

使用工具

测试框架

  • Jest - 基于 jasmine,对react友好。是facebook推出的一款测试框架,集成了 Mocha,chai,jsdom,sinon等功能
  • Jasmine - BDD 风格,自带assert 和 mock
  • Mocha - 全面审核node和浏览器两个端
  • Qunit - 出资 JQ

断言库

  • Chai - 支持所有风格、全面
  • Should
  • export
  • Assert - node环境直接使用

Mock库(主要写一些间谍函数或者屏蔽函数)

  • sinon

Test runner 库

  • Karma

覆盖率工具

  • istambul(伊斯坦布尔,哈哈哈)

准备上手啦!

上手前,先介绍一下大致情况

咱是用vue项目做demo的,但这个应该不影响哈。首次使用的话,我们用了 Mocha + Karma + sinon + chai

新建test-demo项目

这里使用的是 vue-cli2,直接上图

这边选择Karma and Mocha

生成项目,打开文件

test 目录下有unit文件夹

这是Karama配置文件

接着我们打开specs文件,里面有一个HelloWorld.spec.js文件,改文件就是接下来,我们要写测试用例的地方

编写第一个测试用例

  1. 在 helloworld组件中写一个方法
m1 (a, b) {
  return a + b
}
  1. 在HelloWorld.spec.js中写一个测试用例
import Vue from 'vue'
import HelloWorld from '@/components/HelloWorld'
//所有的测试用例都下载describe中
describe('HelloWorld.vue', () => {
  //导入要测试的组件
  const Constructor = Vue.extend(HelloWorld)
  //获取该组件的  this 
  const vm = new Constructor().$mount()
  //开始一个测试用例
  it('should render correct contents', () => {
    expect(vm.$el.querySelector('.hello h1').textContent)
      .to.equal('Welcome to Your Vue.js App')
  })
   it('is m1 add two arguments', () => {
    //获取m1方法
    const m1 = vm.m1
    //使用断言库,(期待m1(1,2)等于3,纯属字面意思,哈哈哈)
    expect(m1(1, 2)).to.equal(3)
  })
})
  1. 控制台运行单元测试
npm run unit

OK,第一个测试用例编写成功,测试通过!

第一个异步单元测试

  1. 在HelloWorld.vue写一个异步函数
async m4 (cb) {
  await axios.get('http://www.xxx.com')
  let data = cb()
  return data
}
  1. 在HelloWorld.spec.js写一个获取axios被调用次数的测试用例,使用sinon
注意,一定要引入promise,否则会报错
import Vue from 'vue'
import HelloWorld from '@/components/HelloWorld'
import axios from 'axios'
import Promise from 'es6-promise'
Promise.polyfill()
describe('HelloWorld.vue', () => {
  const Constructor = Vue.extend(HelloWorld)
  const vm = new Constructor().$mount()
  it('should render correct contents', () => {
    expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Welcome to Your Vue.js App')
  })
  it('is m1 add two arguments', () => {
    const m1 = vm.m1
    expect(m1(1, 2)).to.equal(3)
  })
  it('接口被请求', () => {
    // spy,stub,MOCK
    // spy是可以获取到对应函数的调用信息,但是不能屏蔽
    // stub会拦截掉这个方法
    const m4 = vm.m4
    // 间谍函数
    let axiosspy = sinon.spy(axios, 'get')
    m4(axiosspy)
    // 获取axios被调用次数
    console.log(axiosspy.callCount)
    axiosspy.restore()
  })
})
  1. 控制台运行单元测试
npm run unit

成功打印接口请求次数,但是请注意,spy不能屏蔽该请求,接下来,我们实现接口屏蔽

编写一个屏蔽接口的测试用例

  1. 在HelloWorld.vue写一个异步函数
async m5 (cb) {
  await axios.get('http://www.baidu.com')
  let data = cb()
  return data
}
  1. 在HelloWorld.spec.js写一个屏蔽axios调用的测试用例
  it('接口被屏蔽', async () => {
    // spy,stub,MOCK
    // spy是可以获取到对应函数的调用信息,但是不能屏蔽
    // stub会拦截掉这个方法
    let m5 = vm.m5
    let callback = sinon.stub(axios, 'get')
    let axiosspy = sinon.spy(() => {
      return 4
    })
    expect(await m5(axiosspy)).to.equal(4)
    callback.restore()
  })

  1. 控制台运行单元测试
npm run unit

OK,通过了单元测试

总结

这是第一次尝试单元测试,还是有很多概念性的知识不太懂,但是对于单元测试的话大致也算了解了一下,后面自己有尝试了使用 JEST进行单元测试,大体差不多,语法也很相似,只是JEST有个坑:在jest.conf.js文件中,要把 mapCoverage: true 这一行注释,并且加上

verbose: true, 
testURL: 'http://localhost/'

才能正常运行测试环境。

呼,写文章不易,掘友看了,若是觉得有什么不妥的,请留言哦,感谢了,点赞我就不奢求了,只是个学习记录,不喜勿喷哦~