前端单元测试及其工具介绍(一)

文章目录

前端单元测试及其工具介绍

本篇只是对单元测试可能用到的一些工具进行介绍和例举,具体的vue项目测试环境搭建和测试用例编写,请查看我的其他几篇文章。

为什么需要单元测试

  • 测试肯定是为了减少bug,这没什么好说的。而且测试写好了,减少你的工作量,及时发现问题,定位问题,提高效率,保证质量。最好是一开始编写组件之前,就编写好测试用例,这样,在编写测试用例时,你在脑海中就就可以将组件的雏形构建出来,这样编写组件时就会有很清晰的思路,事半功倍。

  • 前端项目的单元测试不是必须的,特别是业务型项目,增加单元测试反而会成为累赘,增加开发成本且无意义,业务型的项目需求常常变动,UI也经常更改,增加单元测试,需要在开发过程中不断更新开发测试用例,增加开发成本。但是,项目中的一些公共封装,比如公共的组件、公用的功能模块等是可以使用单元测试的。参考:https://www.javascriptcn.com/read-51682.html

单元测试的一些要素

  • 测试框架
  • 测试报表
  • 测试覆盖率
  • 断言
  • mock

测试框架提供测试语法以及单元测试代码的编写,断言和mock提供单元测试编写的辅助工具,可以更方便快捷的编写你的测试用例,而测试报表和测试覆盖率是为了检验你的测试是否通过和测试是否有效的工具。

工具

mocha

介绍

一款js测试框架,主要优点是灵活,可扩展性强。但只提供简单的测试结构,如果需要assert断言,mock等,需要添加第三方库。mocha必须在全局环境中安装,你局部也要安装。

只要程序抛出一个错误,mocha就会认为测试不通过,事实上,只要不抛出错误,测试用例就算通过

API

他只提供了如下两个API

  • describe(name, fn) 定义一组测试

  • it(name, fn) 定义一项测试

// 
// 定义一组测试
describe('test', () => {
    // 定义一项测试
    it('testName', () => {
        // 测试内容
    })
})

上面代码中,一个测试文件包含多个describe块,describe表示定义一组测试,而it则是最小的测试单元,定义一个测试用例。describe可以嵌套describe,一个describe可以包含多个it。你可以根据describe划分业务模块和功能模块的测试,然后里面包含一组组的测试用例。

钩子函数

一个describe中包含了一组钩子函数,他会在测试执行的不同时期执行

  • before():在该区块的所有测试用例之前执行

  • after():在该区块的所有测试用例之后执行

  • beforeEach():在每个单元测试(即it)前执行

  • afterEach():在每个单元测试(即it)后执行

注意

  • Mocha不推荐使用箭头函数作为Callback的函数

  • 不要用例中什么都不做, 推荐使用skip跳过不需要的测试

参考

mocha官方文档中文翻译

阮一峰:mocha实例教程

chai

介绍

他是一个断言库,因为mocha没有自己的断言库,所以需要第三方的断言库。而他就是一个断言库,并且支持三种断言方式:

  • should - BDD风格的断言
  • expect - BDD风格的断言
  • assert - TDD风格的断言

我们这里选择使用expect的风格,因为比较接近自然语法编写。

使用

如果在mocha中,想要判断一个函数执行执行是否符合预期,并在测试其不符合预期时测试失败,那么可能会这么写:

// sum.js
export const sum = (x, y) => {
    return x + y;    
}
import { sum } from '@assets/js/sum.js';
describe('myTest', () => {
    it('测试一', function () {
        if (sum(1, 2) !== 3) {
            // 只要程序抛出一个错误,mocha就会认为测试不通过
            throw new Error('sum函数执行不符合预期');
        }
    });
});

上面代码中,如果每次在测试失败时都需要抛出异常来处理,可能有点繁琐,而且,我们一般都需要按照函数执行结果不等于什么来进行异常捕获,而无法从编程中一眼看上去就知道他的期望等于什么,所以,我们可以使用断言来帮我们封装一下异常处理,并且使想要测试的意图更加清晰。比如使用chai断言的写法:

// 引入chai中的expect函数,其作用就是用于断言的
import { expect } from 'chai';
// 在describe中编写
it('测试二', function () {
    expect(sum(1, 2)).equal(3);
});

结果:

  1 failing
  1) myTest
       测试二:

      AssertionError: expected 2 to equal 3
      + expected - actual

      -2
      +3

      at Context. (dist\webpack:\tests\unit\example.spec.js:24:1)

很明显,使用chai的expect进行断言,不仅语法更为简洁,并且错误信息也更为详细,列出了期望值和真实值,以及出现断言失败的文件和行数,以便我们更好的定位错误。

参考

mochawesome

使用这个模块,可以生成漂亮的HTML格式的测试报告,以便你更好的分析你的测试结果。这个没什么好说的,就是帮你把你的测试结果用html来进行美化。

nyc/Istanbul

介绍

他是一个检查代码测试覆盖率的工具,关于测试覆盖率的介绍,详情查看附录测试覆盖率部分。

注意:不要直接安装istanbul这个npm包,因为它属于已经即将废弃的状态了,请尝试使用nyc,他是istanbul的命令行接口,整合了istanbul库,所以直接安装nyc作为我们的依赖即可。

官网参考:https://istanbul.js.org/integrations

Sinon

在我们需要测试的代码中,有时候测试代码会依赖于其他模块,如果你的测试代码不需要关心其他模块,那么我们可以使用sinon来mock相关模块,将模块之间的测试进行解耦。

karma

定义

Karma是一个基于Node.js的JavaScript测试执行过程管理工具,注意:测试执行过程的管理工具,他和mocha用来做单元测试是有区别的。

介绍

这个karma是一个基于node的js测试运行环境,是谷歌的,他在这里的作用吧,应该是为了配合mocha来完成自动化测试,并让代码在接近真实的浏览器中进行测试,并且可以支持多种浏览器,而且它可以提供istanbul来自动生成覆盖率报告。

其实感觉上来说mocha提供了测试的框架,而karma则提供了测试的运行环境。用mocha编写测试文件,用来做单元测试,用karma来提供测试文件运行时的真实浏览器模拟环境以及他集成的一些诸如测试覆盖率报告以及文件监听等功能来完善以及自动化测试流程。

一个用来做单元测试,一个用来将单元测试自动化,应该就是这么个关系。

一些karma中需要了解的插件以及知识

mocha

  • mocha:Test Framework

  • karma-mocha: karma的插件,为karma定制的mocha

在浏览器中模拟真实的代码运行环境

  • karma-chrome-launcher: chrome启动器

  • karma-phantomjs-launcher: phantomjs启动器(phantomjs叫做无头浏览器,即没有UI的浏览器)

生成测试覆盖率报告

  • karma-coverage: karma定制的代码覆盖了插件

  • istanbul: karma-coverage需要使用到的代码生成代码覆盖率的js库

mocah配合断言库chai

  • chai: 断言库, 可以使用BDD风格的判定

  • karma-chai: karma定制的chai插件

如果你只在node中进行单元测试,那么使用mocha即可,如果想要你的代码在浏览器体验真实的运行效果,那么可以考虑使用karma

参考

https://www.jianshu.com/p/49707d15c529

https://www.cnblogs.com/jasmine-95/p/6054839.html

@vue/test-utils

vue官方的测试vue文件的测试工具,他可以提供对vue组件的测试。在你测试组件时用它会方便很多。

一些约定

  • 测试文件一般放在根目录下的tests文件夹中(一般约定是这个,好像也有用test文件夹的),然后编写测试的js文件一般以:.test.js或者.spec.js结尾,这也是一个约定吧。当然了,这也只是大多数人的一个约定。

  • 测试文件的文件名 = 被测试模块名 + .test.js,最好按分类进行测试模块的文件夹分类。

附录

Unit Testing和E2E Testing

常用的测试有

  • 单元测试(unit testing)
  • 功能测试(feature testing)
  • 集成测试(integration testing)
  • 端对端测试 (End-to-End testing)
  • 性能测试
  • 安全测试

对普通开发者而言,单元测试和功能测试是最常见的两种测试方式。而单元测试是对某一块独立的业务模块进行测试,可以是一个小功能,甚至一个函数。

vue-cli中支持

  • Unit:单元测试

  • E2E:端对端测试

参考

TDD和BDD开发方式

参考文章一

测试覆盖率

覆盖率是用来度量测试完整性的一个手段,同时也是测试技术有效性的一个度量。表达起来可能是:我编写的测试代码对项目中的代码的使用率,即我的测试代码是否对项目中的所有代码都测试到了(可以看作对项目的每一行都执行了)

  • 通过覆盖率数据,可以检测我们的测试是否充分

  • 分析出测试的弱点在哪方面

  • 指导我们设计能够增加覆盖率的测试用例,有效提高测试质量,但是测试用例设计不能一味追求覆盖率,因为测试成本随覆盖率的增加而增加。

参考

Jest

他同mocha一样是一个js测试框架。特点:安装配置简单,内置istanbul,可以查看测试覆盖率,自带断言,jsDom,几乎你需要的单元测试工具都集成了,并且完美支持react组件化测试,开发者一般用这个来测试react。相对于Jest,mocha的配置就显得过于繁琐了。

  • 他和mocah一样拥有四个钩子函数,并且还几乎是一致的功能。

  • Jest的test方法是it方法的一个别名。

上一篇:Vue单元测试(Karma+Mocha+Chai)


下一篇:django项目部署