Skip to content

24-单元测试如何做

24-单元测试如何做

统计信息:字数 4250 阅读9分钟

软件开发过程中需要测试:白盒测试(单元测试)和黑盒测试(点击界面功能)

  • 什么是单元测试
  • 单元测试常用的库
  • VUE中如何使用单元测试

单元测试概念

概念

工程化:为了应付工程体系的不断复杂化,增加一些工具让我们更方便工作

前端工程化:webpack + git + 单元测试(使用软件工程的方法处理前端)

单元测试:对软件中最小的可测试单元进行测试。

单元测试的目的:团队分模块开发(前后端分离),方便定位模块出现问题;保证了代码的质量;测试驱动开发。

单元测试的两种类型:TDD(测试驱动开发)BDD(行为驱动开发)

TDD: 从需求角度看,用户需要什么,如果不是就是代码错误(用户需求分析-编写单元测试-编写代码并通过单元测试-代码重构)

BDD:行为驱动开发:从具体的功能角度出发,结果应该是什么。(从产品角度定义目标-找到目标实现的方法-编写单元测试-实现行为-检查产品)

Mock库作用:如果一个方法中使用另一个方法,可以使用Mock库屏蔽另一个方法带来的影响。

测试用例:测试输入+执行+预期输出结果

测试原则:测试案例需要及时维护修复(测试和代码同步修改)code review:确保代码功能正常;代码符合项目规范

单元测试使用哪些库

单元测试范围

测试框架+断言库+Mock库+test runner+覆盖率工具

测试框架

Jest 集成了断言库和Mock,基于jasmine,对React友好

Jasmine bdd风格,包含 assert + Mock

Mocha需要自己去配置断言库和Mock(适合node和浏览器)

断言库:chai (全面)、should、expect、Assert (node)

Mock库:sinons

TestRunner:karma

覆盖率工具:istanbul

框架中使用单元测试

phantomJS 无头浏览器:不属于任何浏览器的特点,遵循前端的测试规范(主要用于测试)

React 通常使用 Jest 做单元测试;VUE在初始化使用 vue-cli 可以

可以选择Jest,可以选择mocha+chai+sinon自己配置

function a() {
  b();
}
function b() {

}

测试需要增加配置文件

karma.conf.js

module.exports = function karmaConfig(config) {
  config.set({
    browser: ['PhantomJS'],
    frameworks: ['mocha', 'sinon-chai'],
    reporters: ['spec', 'coverage'],
    files: ['./index.js'],
    preprocessors: {
      './index.js': ['webpack', 'sourcemap']
    },
    webpack: webpackConfig,
    webpackMiddleware: {
      noInfo: true
    },
  });
}

webpack.test.config.js

index.js 是框架默认提供的

Package.json

{
  "scripts": {
    "test": "npm run unit",
    "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
  }
}

例子

helloworld.spec.js

import Vue from 'vue';
import HelloWorld from '@/components/HelloWorld';
import Promise from 'es6-promise';
Promise.polyfill();

describe('Hello.vue', () => {
  it('should render correct contents', () => {
    const Constructor = Vue.extend(HelloWorld);
    // 组件构造类
    const vm = new Constructor().$mount();
    expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Welcome to my Vue.js App');
  });

  // 测试方法(异步的方法如何测试)
  it('test function m1', () => {
    const m1 = vm.m1;
    expect(m1(2, 3)).to.equal(5);
  });
  it('async m2 should return 3', () => {
    const m2 = vm.m2;
    m2(1, 2, data => {
      expect(data).to.equal(3);
    });
    m2(1, 2).then((res) => {
      expect(data).to.equal(3);
    });
  });
  // getmes
  it('接口被请求', () => {
    // spy stub
    let axiosspy = sinon.spy(axios, 'get');
    console.log(axiosspy.callCount);
    let callback = sinon.spy(() => {
      return 5;
    });
    const getmes = vm.getmes;
    expect(getmes(callback)).to.equal(4);
  });
});

// 原组件
methods: {
  m1: function(a, b) {
    return a + b;
  },
  m2: function(a, b, fn) {
    setTimeout(() => {
      fn(a + b);
    }, 1000);
  },
  getmes: function(fn) {
    axios.get('www.baidu.com');
    let res = fn();
    this.data = res;
    return data;
  }
}

Last update: November 9, 2024