NodeJS测试框架mocha入门教程


Posted in NodeJs onMarch 28, 2017

NodeJS里最常用的测试框架估计就是mocha了。它支持多种node的assert libs, 同时支持异步和同步的测试,同时支持多种方式导出结果,也支持直接在browser上跑Javascript代码测试。

本文示例大多源于官网示例,部分示例结合需要或自己的感想有所改动。更多介绍请看 官方网址:Mocha on Github

Installation:

当你成功安装nodejs v0.10 和 npm后执行下面这条命令。

# npm install -g mocha

p.s. Ubuntu的注意apt源里的nodejs版本会比较旧,某些module会不支持,请从nodejs官网进行源码安装。

First step to Mocha:

以下为最简单的一个mocha示例:

var assert = require("assert");
describe('Array', function(){
 describe('#indexOf()', function(){
  it('should return -1 when the value is not present', function(){
     assert.equal(-1, [1,2,3].indexOf(5));
   assert.equal(-1, [1,2,3].indexOf(0));
 })
 })
});

describe (moduleName, testDetails) 由上述代码可看出,describe是可以嵌套的,比如上述代码嵌套的两个describe就可以理解成测试人员希望测试Array模块下的#indexOf() 子模块。module_name 是可以随便取的,关键是要让人读明白就好。
it (info, function) 具体的测试语句会放在it的回调函数里,一般来说info字符串会写期望的正确输出的简要一句话文字说明。当该it block内的test failed的时候控制台就会把详细信息打印出来。一般是从最外层的describe的module_name开始输出(可以理解成沿着路径或者递归链或者回调链),最后输出info,表示该期望的info内容没有被满足。一个it对应一个实际的test case
assert.equal (exp1, exp2) 断言判断exp1结果是否等于exp2, 这里采取的等于判断是== 而并非 === 。即 assert.equal(1, ‘1') 认为是True。这只是nodejs里的assert.js的一种断言形式,下文会提到同样比较常用的should.js。
如果exp1和exp2均为字符串,字符串比较出错时则控制台会用颜色把相异的部分标出来。

Asynchronous

Frist step 中的代码显然是个 Synchronous 的代码,那么对于异步代码应该怎么做呢?很简单,在你最深处的回调函数中加done()表示结束。

fs = require('fs');
describe('File', function(){
 describe('#readFile()', function(){
   it('should read test.ls without error', function(done){
   fs.readFile('test.ls', function(err){
  if (err) throw err;
  done();
  });
 })
 })
})

done ()<br> 按照瀑布流编程习惯,取名done是表示你回调的最深处,也就是结束写嵌套回调函数。但对于回调链来说done实际上意味着告诉mocha从此处开始测试,一层层回调回去。

上例代码是test pass的,我们尝试把test.ls改成不存在的test.as。便会返回具体的错误位置。

这里可能会有个疑问,假如我有两个异步函数(两条分叉的回调链),那我应该在哪里加done()呢?实际上这个时候就不应该在一个it里面存在两个要测试的函数,事实上一个it里面只能调用一次done,当你调用多次done的话mocha会抛出错误。所以应该类似这样:

fs = require('fs');
describe('File', function(){
 describe('#readFile()', function(){
   it('should read test.ls without error', function(done){
   fs.readFile('test.ls', function(err){
  if (err) throw err;
  done();
  });
 })
   it('should read test.js without error', function(done){
   fs.readFile('test.js', function(err){
  if (err) throw err;
  done();
  });
 })
 })
})

Pending

即省去测试细节只保留函数体。一般适用情况比如负责测试框架的写好框架让组员去实现细节,或者测试细节尚未完全正确实现先注释以免影响全局测试情况。这种时候mocha会默认该测试pass。
作用有点像Python的pass。

describe('Array', function(){
 describe('#indexOf()', function(){
  it('should return -1 when the value is not present', function(){
 })
 })
});

Exclusive && Inclusive

其实很好理解,分别对应only和skip函数。

fs = require('fs');
describe('File', function(){
 describe('#readFile()', function(){
   it.skip('should read test.ls without error', function(done){
   fs.readFile('test.ls', function(err){
  if (err) throw err;
  done();
  });
 })
   it('should read test.js without error', function(done){
 })
 })
})

上面的代码只会有一个test complete, 只有only的会被执行,另一个会被忽略掉。每个函数里只能有一个only。如果是it.skip ,那么该case就会被忽略。

only和skip共用没有什么实际意义,因为only的作用会把skip屏蔽掉。

fs = require('fs');
describe('File', function(){
 describe('#readFile()', function(){
   it.skip('should read test.ls without error', function(done){
   fs.readFile('test.as', function(err){
  if (err) throw err;
  done();
  });
 })
   it('should read test.js without error', function(done){
 })
 })
})

上面的代码尽管test.as不存在,但是由于skip,依然会显示test complete。

Before && After

单元测试里经常会用到before和after。mocha同时还提供了beforeEach()和afterEach()。
这里为方便阅读用livescript表示,!->可理解成function(){}。细节无需细读,只需通过框架了解这几个函数如何使用便可。

require! assert
require! fs
can = it


describe 'Array', !->
 beforeEach !->
 console.log 'beforeEach Array'

 before !->
 console.log 'before Array'
 
 before !->
 console.log 'before Array second time'

 after !->
 console.log 'after Array'

 describe '#indexOf()', !->
 can 'should return -1 when the value is not present', !->
  assert.equal -1, [1,2,3].indexOf 0
 can 'should return 1 when the value is not present', !->

 describe 'File', !->

 beforeEach !->
  console.log 'beforeEach file test!'

 afterEach !->
  console.log 'afterEach File test!'

 describe '#readFile()', !->
  can 'should read test.ls without error', !(done)->
  fs.readFile 'test.ls', !(err)->
   if err
   throw err
   done!
  can 'should read test.js without error', !(done)->
  fs.readFile 'test.js', !(err)->
   if err
   throw err
   done!

由结果可知(after的使用与before同理),

beforeEach会对当前describe下的所有子case生效。
before和after的代码没有特殊顺序要求。
同一个describe下可以有多个before,执行顺序与代码顺序相同。
同一个describe下的执行顺序为before, beforeEach, afterEach, after
当一个it有多个before的时候,执行顺序从最外围的describe的before开始,其余同理。

Test Driven Develop (TDD)

mocha默认的模式是Behavior Driven Develop (BDD),要想执行TDD的test的时候需要加上参数,如

mocha -u tdd test.js

前文所讲的describe, it, before, after等都属于BDD的范畴,对于TDD,我们用suite, test, setup, teardown。样例代码如下:

suite 'Array', !->
 setup !->
 console.log 'setup'

 teardown !->
 console.log 'teardown'

 suite '#indexOf()', !->
 test 'should return -1 when not present', !->
  assert.equal -1, [1,2,3].indexOf 4
NodeJs 相关文章推荐
PHPStorm 2020.1 调试 Nodejs的多种方法详解
Sep 17 NodeJs
Nodejs实现的一个简单udp广播服务器、客户端
Sep 25 NodeJs
基于NodeJS的前后端分离的思考与实践(二)模版探索
Sep 26 NodeJs
NodeJS中Buffer模块详解
Jan 07 NodeJs
Nodejs 搭建简单的Web服务器详解及实例
Nov 30 NodeJs
nodejs入门教程三:调用内部和外部方法示例
Apr 24 NodeJs
nodejs socket实现的服务端和客户端功能示例
Jun 02 NodeJs
nodejs 图解express+supervisor+ejs的用法(推荐)
Sep 08 NodeJs
Nodejs 发布自己的npm包并制作成命令行工具的实例讲解
May 15 NodeJs
nodejs 递归拷贝、读取目录下所有文件和目录
Jul 18 NodeJs
nodejs中使用worker_threads来创建新的线程的方法
Jan 22 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 NodeJs
nodejs模块nodemailer基本使用-邮件发送示例(支持附件)
Mar 28 #NodeJs
angular2+nodejs实现图片上传功能
Mar 27 #NodeJs
深入nodejs中流(stream)的理解
Mar 27 #NodeJs
nodejs学习笔记之路由
Mar 27 #NodeJs
NodeJS处理Express中异步错误
Mar 26 #NodeJs
简单好用的nodejs 爬虫框架分享
Mar 26 #NodeJs
nodejs开发——express路由与中间件
Mar 24 #NodeJs
You might like
深入分析php之面向对象
2013/05/15 PHP
php伪静态之APACHE篇
2014/06/02 PHP
php in_array() 检查数组中是否存在某个值详解
2016/11/23 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
2019/12/12 PHP
JavaScript的9个陷阱及评点分析
2008/05/16 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(上:事件篇)
2010/03/24 Javascript
jquery实现图片灯箱明暗的遮罩效果
2013/11/15 Javascript
js定时器(执行一次、重复执行)
2014/03/07 Javascript
js下将阿拉伯数字每三位一逗号分隔(如:15000000转化为15,000,000)
2014/06/02 Javascript
javascript实现网页中涉及的简易运动(改变宽高、透明度、位置)
2015/11/29 Javascript
第一次接触神奇的Bootstrap基础排版
2016/07/26 Javascript
jQuery模拟完美实现经典FLASH导航动画效果【附demo源码下载】
2016/11/09 Javascript
JS正则表达式学习之贪婪和非贪婪模式实例总结
2016/12/26 Javascript
BootStrap组件之进度条的基本用法
2017/01/19 Javascript
详解nodejs微信公众号开发——1.接入微信公众号
2017/04/10 NodeJs
JavaScript输入框字数实时统计更新
2017/06/17 Javascript
基于Vue单文件组件详解
2017/09/15 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
JS运动特效之链式运动分析
2018/01/24 Javascript
vuejs选中当前样式active的实例
2018/08/22 Javascript
vue2 设置router-view默认路径的实例
2018/09/20 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
2020/06/17 Javascript
vue.js实现h5机器人聊天(测试版)
2020/07/16 Javascript
在vue项目中 实现定义全局变量 全局函数操作
2020/10/26 Javascript
[06:23]2014DOTA2西雅图国际邀请赛 小组赛7月12日TOPPLAY
2014/07/12 DOTA
python中关于日期时间处理的问答集锦
2013/03/08 Python
python中的对象拷贝示例 python引用传递
2014/01/23 Python
Python3之不使用第三方变量,实现交换两个变量的值
2019/06/26 Python
django-crontab 定时执行任务方法的实现
2019/09/06 Python
TensorFlow使用Graph的基本操作的实现
2020/04/22 Python
如何基于Python代码实现高精度免费OCR工具
2020/06/18 Python
探讨HTML5移动开发的几大特性(必看)
2015/12/30 HTML / CSS
俄罗斯苹果优质经销商商店:iPort
2020/05/27 全球购物
单位委托书范本(3篇)
2014/09/18 职场文书
2014年平安创建工作总结
2014/11/24 职场文书
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
2021/05/27 Servers