1

前面两篇已经把,js测试的模式,框架,断言库基本介绍了一遍。这里,我们要上升到整体测试架构上来.
首先,单元测试的对象是模块,这里我们就要将自己测试目标调整到对模块测试上来。所以,这里我们需要使用CommonJS或者es6的模块的写法了。
另外需要了解,mocha框架测试的一些基本原理。 通过建立清晰的工程目录,才能让你的测试更加清晰。

es6模块测试

模块语法我这里提及一点。
现在前端比较流行的模块写法有两种,一种是commonJS规范,另外一种是未来es6的普遍写法。
commonJS规范写法:

//写一个模块并且导出,存放在add.js文件下
var add = (num1,num2)=>num1+num2;
exports.add = add;
//引入add.js文件并调用
var test = require('./add.js');
test.add(1,2);  //值应该为3

es6的写法:

var add = (num1,num2)=>num1+num2;
export {add};
//引入模块
import {add} from "./demo.js";
console.log(add(1,2));

但是由于nodeJS默认支持的是commonJS的写法,所以上文的es6只当做介绍吧。

基本工程目录

一个良好的工程目录,能够帮助你测试成本降到最低。这里我们以mocha为基本框架。 mocha测试会默认以你的test目录作为测试文件所在。即,你的所有测试用例都应该放到test文件夹下面. 而且如果以后你去写一个插件,并且附上test目录,这是能够让人相信你的插件的可用性的(因为我已经测试过了呀~).
don't waste time~
基本目录结构应该想这样的.

test
src(js)
... //相应的配置文件,比如makefile,.babelrc等

有兴趣的同学可以看一下。我的目录
Ok,目录搭好了之后。开始说一下mocha测试的内涵了.
在前文,使用mocha测试的时候
使用的命令如下:

mocha test.js

而在这样的目录结构中(在和node_modules同级目录下),可以直接使用

mocha     //后面不要任何参数

他便会遍历你的test文件夹的第一层js文件,并找出测试语句并测试。
但是,我们在测试的时候往往还需要分目录进行测试.
所以这里需要使用到mocha的一个参数.

mocha --recursive

recursive中文意思是递归的意思。那,这就很明显了。 使用recursive的参数,mocha会遍历你目录下所有的文件,执行测试。
这也是mocha最有用的一个参数.
另外,想想,如果你的测试用例写错了。那么你需要手动进行更改。 而且改动完了之后还需要重启mocha,这尼玛超级烦人的哎喂。 所以,mocha之所以这么吸引人就是因为他的人性化。
mocah提供了你一个参数--watch

mocha --watch

这样mocha框架会持续监听你的文件,如果有改动的话则会重新测试.
还有一个样式文件,可以输出一些不一样的mocha风格(要记住,做一名有情怀的程序员)
这里我提供给大家两个我比较喜欢的。一个是萌系,一个是职场魅力.

//萌系
mocha --reporter nyan
//职场魅力
mocah --reporter tap

上张图吧。

本人,是个宝宝。 所以超级喜欢第二个。 但是到大人(leader)面前,会用tap来装装逼的.
这时候,我想想应该有人会崩溃的。
md,这么多参数,我怎么配呀。。。
mocha早已看穿一切。
它用mocha.opts让你不知不觉的跪在地板上。
只要我们把 mocha.opts配置好了,那么我们就可以直接使用

mocha

运行测试
个人比较青睐于这3个参数.另外mocha.opts文件是放在test的根目录下的.

--recursive (必不可少)
--reporter nyan(萌萌哒)
--watch

OK. 我这里有个实例,大家可以参考。
还有,如果你想生成一个测试规格文件(markdown),可以直接使用

mocha --recursive -R markdown > spec.md

如果你想生成html文件,也可以使用

mocha --recursive -R doc > spec.html

ok~ 基本操作,我们已经有点心得体会了。 不过,就像我所说的那样,测试
不仅能让你的代码,完美通过。还要保证的你代码质量有相当高的质量. 而 保证你高质量代码的工具就是代码覆盖率测试。这一块算是独立于单元测试的。 在前端最常用的就是使用istabul.
首先应该下载istanbul:

npm install -g istanbul

这时候,istanbul已经下载到你的全局目录下。 你可以在你电脑的任意角落运行istanbul的相关命令.但是,本宝宝不想码字。所以,我这里仅仅介绍istanbul的官网上面推荐的一个黄金order:

istanbul cover xxx.js

使用istanbul检查指定的文件,并且他会在当前的目录下,生出一个coverage directory。 里面包含了你测试文件的GUI(就是HTML啦~),你可以打开来看一下,挺好看的哦(才怪).
如果你想测试test目录下的话,可以使用:

istanbul cover test/*.js

但是,结果肯定是不会通过的,因为istanbul的默认引擎是ECMA的,但是, 在test目录下,充斥的是mocha测试框架的地盘诶~


istanbul: js,js,js快开门,我是你的测试妈妈呀~
js: 不开,不开,我不开,mocha妈妈没回来

就是这个感觉,所以造成的问题就是,istanbul根本动不了test目录下的。 呵呵,你以为istanbul就这样放弃了吗? 你知道istanbul的学名叫什么吗? 地毯推销
不认我这个妈? 那我当你奶奶吧。
就这样。istanbul又多出一个命令:

istanbul cover _mocha

现在istanbul比mocha更高一级。 他会骑着mocha驰骋在测试的领域里。mocha在哪,他就在哪。当mocha运行完的时候,他就会生成测试报告.
还记得,上面所说的mocha.opts吗?
其实,这只是最流行的做法的一块垫脚石,最流行的做法就是配置makefile文件。有兴趣的同学,可以参考我的前一篇blog.
这时候,我们就可以使用makefile来搭载我们需要进行测试的用例了。

makefile构建测试框架

我们先来看一个比较简单的:

test:
        istanbul cover _mocha
.PHONY:test

由于在本宝宝的电脑上,istanbul和mocha都是全局安装,所以,这里不需要指明指定的.bin文件的目录。而且,mocha的参数已经在mocha.opts里面已经配置好了。 不过,如果你想自定义一些参数的话,可以在_mocha后面传入参数,这时候,你可以完全抛弃mocha.opts了。因为make已经让你知道什么叫做 muscle

OPTS:=--recursive --reporter nyan --watch
test:
        mocha $(OPTS)
cover:
        istanbul cover _mocha -- $(OPTS)
.PHONY:test

当然,比较装逼的做法就是,就是使用本地的node_modules,确保版本的统一(不过,推荐安装到全局,这样其他项目也方便用。而且方便配置).

show u the code

ISTANBUL=./node_modules/.bin/istanbul
_MOCHA=./node_modules/.bin/_mocha
MOCHA=./node_modules/.bin/mocha
OPTS:=--recursive --reporter nyan --watch
test:
        @$(MOCHA) $(OPTS) #省略命令的输出
cover:
        @$(ISTANBUL) cover $(_MOCHA) -- $(OPTS)
.PHONY:test cover

这只是一个小小的示范。 随着你项目的壮大,你后面的测试会越来越复杂,makefile在后面的测试体现的效果也越大。
不过通常,我使用makefile还有一个特点就是它强大的组合命令能力。我在前一篇blog里面也说过了。 这里再炒一遍。
makefile的基本格式为:

target:prerequisties
[TAB]command

他组合命令就体现在prerequisties。
我们可以使用prerequisties组合出我们想要的测试效果.

testDemo:
        mocha 'test/test.js'
testNest:testDemo
        mocha 'test/nested/test1.js'

当你指定make testNest的时候,执行顺序会testDemo-> testNest.

测试API

这里就主要针对于nodeJS而言的,当我们写好一个接口的时候,都需要进行相应的测试,才能交给前端去使用,不然的话,真的是!害!人!害!己啊。
以前没有了解测试,通常是使用网页测试,比如Advanced REST client,导致的结果就是测试过的后面加需求之后,更改,然后又出现以前的bug,然后测试的demo就删了写(蛋疼),而不能有很好的目录测试。
这里,介绍一个很棒的测试框架supertest.该框架能够模拟你的接口,并且发送相应的请求过去,然后对返回的数据进行验证,而且他设置的结果是ephmeral(短暂的),所以这就省去了你开启接口,然后关闭,然后在打开这样无脑的行为。 这样,不仅能让你很好的保存你测试的用例,并且可以实现完美的自定义化.
看个demo:

var express = require("express");
var request = require("supertest");
var app = express();
var expect = require('chai').expect;

// 定义路由
app.get('/user', function(req, res){
  res.status(200).send({ name: 'get it' });
});

describe('GET /user', function(){
  it('respond with json', function(done){
    request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function (err, res) {
        if (err){
          done(err);
        }
        expect(res.body.name).to.equal('get it');
        done();
      })
  });
});

要知道测试API的时候,是异步测试,所以这里需要引入mocha的done测试,让你能够很好的解决异步的问题。
另外,一般测试的时候,我们并不需要这么写的详细,写的时候一定要找准自己的测试点。 一般而言,测试一个接口就是测试他的 类型,返回值,发送数据格式等基本项。
上面只是一个简单的demo,详细的可以参考supertest的测试用例.
栗子:

// 定义路由
describe('POST /user', function(){
  it('should work with .send() etc', function(done){
    var app = express();

    app.use(bodyParser.json());

    app.post('/', function(req, res){
      res.send(req.body.name);
    });

    request(app)
    .post('/')
    .send({ name: 'jimmy' })
    .expect('jimmy', done);
  });
});

持续集成(CI)

首先说明一下,什么是持续集成
此处输入图片的描述
(via 阮老师)
持续集成具体的说就是你一天push很多次代码到github上,并且检查你所有代码的测试是否通过。
对于github,travis-cli就是用来帮助你完成这一系列构建的。
这里,我讲解一下基本的配置流程。

  1. 打开travis-cli官网,然后绑定你的github账号

  2. 在你git根目录下,新建.travis.yml文件。根据你项目的语言选择合适的,作为前端的宝宝。 我们使用node就可以了

language: node_js
node_js:
  - "5"
  - "4"

3. 在npm scripts里面设置test命令,通常情况下使用

test:mocha --recursive --reporter spec

4.最后push你的代码到远端仓库, travis-cli会自动执行npm run test. 进行检测。 所以,这里的test一定要写全,需要对你所有的检测用例都检测一遍才可以。
这里,我有个demo.大家如果有兴趣,可以参阅。
其实,还有一个UI测试。这里,我就不做过多的赘述了, 因为,宝宝觉得UI测试,还是直观上方便一些。
在正式的场合里面(leader), 多写测试,不仅能让你的代码有更好的可信度,而且也能让你置于和产经撕逼的不败地位。
ending~


villainhr
7.8k 声望2.2k 粉丝