mocha

80520394 2019-06-29

这篇文章百分之99都是照着mocha官网的内容来写的。就是个扫盲文,如果你想获得关于mocha更深层次不为人知的内容,还是别浪费你宝贵的十几分钟了,马上叉掉。不为啥的,我就做个笔记,方便以后复习。

mocha(抹茶)是一款javascript测试框架,支持在node和浏览器端运行。它比QUnit更完善,可扩展性更强。在官网上,对它的描述就是简单,可扩展,有趣。(有趣是什么鬼)

使用

// 1
npm install mocha -g 
mocha ./test.js

// 2
npm install mocha --save-dev 
node .node_modules/mocha/bin/mocha ./test.js

主要api

mocha只有两个主要的api。

  • describe(name, fn) 定义一组测试
  • it(name, fn) 定义一项测试
describe('proxy', function(){
  it('proxy data 1', function(done){
    this.timeout(1000)
    assert.ok(true, 'fail')
  })

你也可以在一组测试里面再定义一组测试

describe('group1', function(){
  describe('child1', function(){
   })
})

只测试其中某一组测试

describe('test', function(){
  describe.only('testc1', function(){
  })
 })

跳过某一组测试

describe('test', function(){
  describe.skip('testc1', function(){
  })
 })

断言

mocha没有佩戴自己的断言库,它允许你使用第三方断言库,如node 内置的assert, chai等。只要程序抛出一个错误,mocha就会认为测试不通过。

const assert = require('assert') // 使用node内置的断言库

describe('proxy', function(){
  it('proxy data 1', function(done){
    this.timeout(1000)
    assert.ok(true, 'fail')
  })

node assert 断言

  • assert.fail(String | Error)
    抛出一个AssertionError, 如果参数是一个Error,则会抛出这个Error。
  • assert.ifError(any)
    只要any 不等于undefined | null 就抛出any
  • assert.ok(value[,maessage])
    测试value 是否为真值
  • assert.equal(actual, expected [,message]) | assert.notEqual(actual, expected [,message])
    对actual 和 expected 执行 == 比较
  • assert.strictEqual(actual, expected [,message]) | assert.notStrictEqual(actual, expected [,message])
    对actual 和 expected 执行 === 比较
  • assert.deepStrictEqual(actual, expected[,message]) | assert.notDeepStrictEqual()
    测试是否深度全等, 执行的是=== 比较

异步测试

  • 回调形式
describe('Array', function(){
  it('should correct', function(done){
    setTimeout(done,1000)
  })
})

如果done()执行的时候有参数,如done('错误'), 那么mocha判定测试不通过。 你也可以直接传入一个Error对象到done函数中,如done(new Error('fail'))

  • promise的形式
describe('Array', function(){
  it('should correct', function(){
    return Promise.resolve()
  })
})

如果it 函数的返回值是一个promise, 将被是为是一个异步测试。并且根据promise的fullfill状态来决定测试是否通过。
值得注意的是,当你觉得使用promise的形式时候,你就不应该再it的回调函数声明参数done。这个会让mocha认为你其实是想通过done的形式来完成异步测试的。

describe('Array', function(done){ // 这个done是不需要的。
  it('should correct', function(){
    return Promise.resolve()
  })
})
  • 使用async-await
describe('Array', async function(done){ // 这个done是不需要的。
  it('should correct', function(){
    let result = someAsyncOperation()
    assert.ok(true, result)
  })
  
})

箭头函数

mocha不提倡使用箭头函数,因为it, describe都是绑定mocha context执行的,在箭头函数中,无法获取到mocha context。如以下会报错

describe('Array', () => {
  it('shoule correct', (done) => {
     this.timeout(1000) // can not read property timeout of undefind
  })
})

hook

mocha 在整个测试周期中,提供了一组hook钩子来让开发者在测试开始之前准备环境或者是测试完成之后清理环境。

describe('hooks', function() {

  before(function() {
    // runs before all tests in this block
  });

  after(function() {
    // runs after all tests in this block
  });

  beforeEach(function() {
    // runs before each test in this block
  });

  afterEach(function() {
    // runs after each test in this block
  });

  // test cases
});

异步钩子
在钩子函数中传入done,并且在异步钩子完成时调用它。

describe('hooks', function() {

  before(function(done) {
    // runs before all tests in this block
    setTimeout(() => {
      done() // 2000ms之后才会执行下一个钩子
    }, 2000)
  })
});

mocha默认的测试超时时间是2000ms,如果你的异步钩子准备时间超过2000ms,请事先声明超时时间

在浏览器端测试

以后补上

vscode 插件

vscode 上面有一个辅助mocha测试的插件 mocha sidebar。

mocha

  • New code coverage support
  • see all tests in vscode side bar menu
  • git lens for running/debugging directly form the code
  • decorations which shows test status(pass/fail/not run) from code
  • run tests for each level hierarchy from all tests to a single test(and each describer of course)
  • debug tests for each level hierarchy from all tests to a single test(and each describer of course)
  • auto run tests on file save
  • see tests results directly on the code
  • run/debug results directly from the code
  • see test errors as decoration
  • NEW add context menu on folders in explorer to set subdirectory (#2).

设置使用babel-register
在vscode的首选项设置如下:

"mocha.requires": ["babel-register"]

mocha sidebar 0.20.22 版本目前只支持babel 6, 如果你使用babel 7 ,那么你就只能在命令中运行测试

mocha --require @babel/register xxx.js

ES6 的module 语法

ES6的import 和 export 在node中并没有实现,所以我们需要通过Babel转换ES6的模块语法。

npm install babel@6 babel-preset-env babel-register

//.babelrc
{
  "presets": ["env"]
}

现在你可以在启动时加入--require参数来让使用了ES6 import/export语法的测试文件在加载时使用babel编译。

mocha --require babel-register ./test/test.js
import _ from 'lodash'
describe('Array', function(){
  it('should correct', function(){
    return Promise.resolve()
  })
})

如果你不使用--require参数,那么你需要显式使用babel-register

// index.js
require('babel-register')
require('./test.js')

// test.js
import _ from 'lodash'
describe('Array', function(){
  it('should correct', function(){
    return Promise.resolve()
  })
})

// comman line
mocha ./index.js

babel-register 会在node 的require中注入一个钩子,让所有以.es6, .jsx, .js, .es作为后缀结尾的文件在require的时候都先经过babel编译。这样子我们在index.js require('./test.js')的时候,就已经将import 语法转换为requrie语法了。

相关推荐