前端单测的那些事

前言

由于常常须要维护一些大型的业务项目和一些本身的开源项目,因此为了更好的“规范”代码质量和迭代的稳定性,开始写了一些单测。下面也主要是本身的一些总结吧,因为测试工具和框架不少,这里只介绍一些browser端经常使用的测试工具,文中若是有问题也欢迎拍正!!🙂javascript

为什么要测试

以前咱们开发项目的时候,老是会忽略去写一写单测,大多数缘由多是以为没有时间或者是浪费时间。并且还须要去维护测试用例。 其实通常项目随着时间的迁移,会变得愈来愈复杂和庞大,这时候若是咱们对某一个公共模块改动,而其余人也依赖了这个模块,可能就会致使别人的功能出现bug。 有了自动化测试,开发者会更加信任本身的代码。开发者不再会害怕将代码交给别人维护,不用担忧别的开发者在代码里搞“破坏”。后人接手一段有测试用例的代码,修改起来也会更加从容。测试用例里很是清楚的阐释了开发者和使用者对于这端代码的指望和要求,也很是有利于代码的传承。html

一些概念

TDD (Test Driven Development)

TDD 也就是测试驱动开发,简单的说,即在写任何功能代码以前,先写它的测试代码。具体步骤:前端

  • 根据须要编写一个测试用例
  • 编写功能代码,以让刚才的测试用例经过
  • 逐步补充测试用例
  • 修改功能代码使新增的测试用例和原来的都经过
  • 重构,包括功能代码和测试用例

BDD(Behaviour Driven Development)

BDD 即 行为驱动开发,能够理解为也是 TDD 的分支,即也是测试驱动,但 BDD 强调的是写测试的风格,即测试要写得像天然语言,运用一些好比expect、should等跟天然语言相近的断言,让项目的各个成员甚至产品都能看懂测试,甚至编写测试。java

写法对比

不论是 TDD 仍是 BDD,咱们来对比一些两者的写法:node

// TDD
  suite('Array', function() {
    setup(function() {
    });

    test('equal -1 when index beyond array length', function() {
      assert.equal(-1, [1,2,3].indexOf(4));
    });
  });

  // BDD
  describe('Array', function() {
    before(function() {
    });

    it('should return -1 when no such index', function() {
      [1,2,3].indexOf(4).should.equal(-1);
    });
  });
复制代码

简单的看, BDD 风格写的会更容易理解,更加语义化。webpack

断言(assert)

在单元测试时,开发预计在程序运行到某个节点位置,须要判断某些逻辑条件必须知足,这样下面的一些业务逻辑才能够进行下去,若是不知足,程序就会"报错"甚至是"崩溃"。断言在单测中,也是主要用来肯定某段程序执行结果应该是某个值这样的一个预期。git

一些断言库的比较

断言库即提供一套 API 帮助开发者在单元测试的过程当中断定某个值是否符合预期,好比:es6

should.js
value.should.equal(1);
  value.should.be.an.Object();
复制代码
expect.js
expect(value).to.be(1)
expect(value).to.be.an('object')
复制代码

chai

Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.github

chai 提供了三种断言风格来分别适用于 BDD 和 TDD。expect/should API 对应BDD风格,Assert API 对应TDD风格。 web

image

测试框架

所谓"测试框架",就是运行测试的工具。经过它,能够为JavaScript应用添加测试,从而保证代码的质量。

Mocha

Mocha(发音"摩卡")诞生于2011年,是如今最流行的JavaScript测试框架之一,在浏览器和Node环境均可以使用。 更多关于mocha的使用和介绍能够参考阮老师的这篇文章测试框架 Mocha 实例教程

Jasmine

Jasmine 不依赖于任何框架,因此适用于全部的 Javascript 代码。使用一个全局函数 describe 来描述每一个测试,而且能够嵌套。describe函数有2个参数,一个是字符串用于描述,一个是函数用于测试。在该函数中可使用全局函数it 来定义Specs,也就是单元测试的主要内容, 使用 expect 函数来测试:

describe("A suite is just a function", function() {
  var a;
  it("and so is a spec", function() {
    a = true;
    expect(a).toBe(true);
  });
});
复制代码

前端测试工具

相比于服务端开发,前端开发在测试方面始终面临着一个严峻的问题,那就是浏览器兼容性。前端开发中浏览器兼容性是一个永远的问题,并且我认为即便解决了浏览器的兼容性问题,将来在移动开发方面,设备兼容性也是一个问题。

因此在自动化测试方面也是如此,即便全部的单元测试集中在了一个runner中,前端测试仍然要面对至少4个浏览器内核以及3个电脑操做系统加2个或更多移动操做系统,况且还有令移动开发人员头疼的Android的碎片化问题。不过能够安心的是,早已存在这样的工具能够捕获不一样设备上的不一样浏览器,并使之随时更新测试结果,甚至能够在一个终端上看到全部结果。下面咱们主要介绍 Karma

Karma

Karma是一个基于 Node.js 的 JavaScript 测试执行过程管理工具(Test Runner)。该工具可用于测试全部主流Web浏览器,也可集成到 CI(Continuous integration)工具,也可和其余代码编辑器一块儿使用。这个测试工具的一个强大特性就是,它能够监控(Watch)文件的变化,而后自行执行,经过console.log显示测试结果。

文档

Istanbul

测试的时候,咱们经常关心,是否全部代码都测试到了。 这个指标就叫作"代码覆盖率"(code coverage)。它有四个测量维度。

  • 行覆盖率(line coverage):是否每一行都执行了?
  • 函数覆盖率(function coverage):是否每一个函数都调用了?
  • 分支覆盖率(branch coverage):是否每一个if代码块都执行了?
  • 语句覆盖率(statement coverage):是否每一个语句都执行了?

这个软件以土耳其最大城市伊斯坦布尔命名,由于土耳其地毯世界闻名,而地毯是用来覆盖的。

详细的文档参考阮老师的代码覆盖率工具 Istanbul 入门教程

动手!

下面咱们来搭建一个ES6 + jasmine + karma + Istanbul + webpack 的基础测试工具。 首先来搭建一个简单的es6环境:

mkdir example

cd example

npm i babel-core bable-loader babel-preset-env --save
复制代码

而后建立.babelrc文件

{
    "presets": [
        "env"
    ]
}
复制代码

接着咱们须要安装 karma 测试工具:

$ npm install karma --save-dev

$ npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
复制代码

接下来初始化karma:

karma init
复制代码

image

这样目录中便会多了一个karma.conf.js这样的一个文件。为了在测试的时候可使用es6,咱们须要使用karma-webpack

npm i webpack karma-webpack --save
复制代码

接下来,就是咱们熟悉的工做了,写一个加载测试脚本的webpack配置文件,好比webpack.test.js:

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};
复制代码

再改写一下咱们的karma.conf.js, 引入webpack:

const webpack = require('../webpack.config')

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'test/**/*.spec.js'
    ],
    exclude: [
    ],
    preprocessors: {
      'test/add.spec.js': ['webpack']
    },
    webpack: webpack,
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    concurrency: Infinity
  })
}
复制代码

运行karma start

image

当前咱们的reporters设置的是progress,因此只会展现最终测试结果,和执行错误的语句。若是你想看到每一条的执行结果,能够安装karma-spec-reporter

npm install karma-spec-reporter --save-dev
复制代码

而后加入spec到karma.conf.js 的 reporters中:

reporters: ['spec']
复制代码

这样就会生成这样的形式报告:

image

其次咱们须要添加istanbul进行代码覆盖率测试。首先咱们须要安装一个babel插件:

npm install babel-plugin-istanbul --save-dev 
复制代码

而后修改咱们的.babelrc文件:

{
  // ...
  "env": {
    "test": {
      "presets": ["env"],
      "plugins": ["istanbul"]
    }
  }
}
复制代码

经过使用.babelrc里的env属性,当咱们经过设置BABEL_ENV=test的时候即可以去执行代码测试的相关插件,这在复杂项目中的测试配置中颇有用。 接下来,为了能生成覆盖率测试报告,咱们还须要安装一个 karma Istanbul 插件karma-coverage:

npm install karma karma-coverage --save-dev
复制代码

而后咱们改一下package.json里面的script脚本:

"scripts": {
    "test": "cross-env BABEL_ENV=test karma start test/karma.conf.js"
}
复制代码

运行

npm run test
复制代码

打开 coverage里面的index.html文件:

image

能够看到覆盖率的一些测试结果。可是这样有点不太方便,但愿能能够直接在控制台输出就行了。因此咱们须要改一下karma.conf.js文件,加上这样一个属性:

coverageReporter: {
    dir: './coverage',
    reporters: [
        { type: 'lcov', subdir: '.' },
        { type: 'text-summary' } // 在控制台输出摘要
    ]
}
复制代码

这样咱们在控制台即可以打印出基本的覆盖率测试结果:

image

至此。已经完成了一个测试环境的搭建,能够知足大部分工程的单测配置。

结语

可能平时因为你们更加关心业务代码,而会忽略一些前端的测试工做,网上的资料也是零零碎碎的,没有一个系统的总结和介绍。这里整理了一些测试工具的使用方法,但愿能够对你有所帮助。而后本文全部代码和原始出处发表在我的博客中。也欢迎阅读以前的博文:

muwoo 的 blogs

单测demo

参考文章

测试框架 Mocha 实例教程

代码覆盖率工具 Istanbul 入门教程

Node.js 单元测试:我要写测试

关于前端开发谈谈单元测试

相关文章
相关标签/搜索