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 相关文章推荐
使用forever管理nodejs应用教程
Jun 03 NodeJs
Nodejs实现的一个简单udp广播服务器、客户端
Sep 25 NodeJs
nodejs爬虫抓取数据乱码问题总结
Jul 03 NodeJs
NodeJS中的MongoDB快速入门详细教程
Nov 11 NodeJs
Nodejs多站点切换Htpps协议详解及简单实例
Feb 23 NodeJs
NodeJs模拟登陆正方教务
Apr 28 NodeJs
Nodejs进阶之服务端字符编解码和乱码处理
Sep 04 NodeJs
Nodejs中使用phantom将html转为pdf或图片格式的方法
Sep 18 NodeJs
nodejs 十六进制字符串型数据与btye型数据相互转换
Jul 30 NodeJs
NodeJS使用Range请求实现下载功能的方法示例
Oct 12 NodeJs
详解Nodejs get获取远程服务器接口数据
Mar 26 NodeJs
详解微信小程序-获取用户session_key,openid,unionid - 后端为nodejs
Apr 29 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调用Java对象的方法
2006/10/09 PHP
destoon实现资讯信息前面调用它所属分类的方法
2014/07/15 PHP
php中常量DIRECTORY_SEPARATOR用法深入分析
2014/11/14 PHP
PHP如何获取Cookie并实现模拟登录
2020/07/16 PHP
可缩放Reloaded-一个针对可缩放元素的复用组件
2007/03/10 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
2011/02/24 Javascript
JS打印gridview实现原理及代码
2013/02/05 Javascript
JavaScript Serializer序列化时间处理示例
2014/07/31 Javascript
JavaScript给input的value赋值引发的关于基本类型值和引用类型值问题
2015/12/07 Javascript
微信小程序获取循环元素id以及wx.login登录操作
2017/08/17 Javascript
webpack 3.X学习之多页面打包的方法
2018/09/04 Javascript
详解webpack2异步加载套路
2018/09/14 Javascript
vue 搭建后台系统模块化开发详解
2019/05/01 Javascript
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
2019/09/17 Javascript
Vue 中 a标签上href无法跳转的解决方式
2019/11/12 Javascript
解决vue中axios设置超时(超过5分钟)没反应的问题
2020/09/04 Javascript
[20:46]Ti4循环赛第三日VG vs DK
2014/07/12 DOTA
深入源码解析Python中的对象与类型
2015/12/11 Python
Python实现七彩蟒蛇绘制实例代码
2018/01/16 Python
python2与python3共存问题的解决方法
2018/09/18 Python
python通过paramiko复制远程文件及文件目录到本地
2019/04/30 Python
pandas.DataFrame的pivot()和unstack()实现行转列
2019/07/06 Python
Python的形参和实参使用方式
2019/12/24 Python
python之生成多层json结构的实现
2020/02/27 Python
详解BeautifulSoup获取特定标签下内容的方法
2020/12/07 Python
Django自带的用户验证系统实现
2020/12/18 Python
python实现文件+参数发送request的实例代码
2021/01/05 Python
css3实现可滑动跳转的分页插件示例
2014/05/08 HTML / CSS
CSS3中引入多种自定义字体font-face
2020/06/12 HTML / CSS
钉钉企业内部H5微应用开发详解
2020/05/12 HTML / CSS
手工制作的意大利皮革运动鞋:KOIO
2020/01/05 全球购物
外语学院毕业生的自我鉴定
2013/11/28 职场文书
工程造价专业大学生职业规划范文
2014/03/09 职场文书
超市创意活动方案
2014/08/15 职场文书
公司新员工欢迎词
2015/09/30 职场文书
thinkphp 获取控制器及控制器方法
2021/04/16 PHP