Mocha中文指南

简介:

mocha是一款比较流行的测试框架,出自TJ之手,跟jasmine相比,它有灵活的断言语法,测试提示也比较友好,其它方面跟jasmine类似.

使用条件

  • npm install -g mocha

  • mocha *.js

mochajasmine一个显著区别在于,它的断言库不是固定的,支持nodejs自带的assert库,should.js,expect.js,chai,better-assert,然后也支持BDD语法的describeit.

因为should.js也是TJ写的,所以这里重点介绍它的断言语法,更多它的API使用文档,可以点击这里

should.js

下面重点介绍它的一些常用手法,测试环境可以使用mocha

先说下,should.js的一个特点,就是它支持友好语法的链式调用,这些语法其实什么都没做,只是编写比较友好,方便阅读,常见的语法有下面这些

be,an,of,a,and,have,with,is,which,the,在should后面加上not代表相反的意思.

结合比较操作方法,看看下面一个简单的例子

require('should');

describe('test should.js', function(){
    it('test chain', function(){
        (10).should.is.be.the.eql(10);
    });
});

上面例子中的is,be,the其实没有顺序要求,读起来怎么友好就怎么写,因为它们什么都没做,只是返回should.js包装函数.

ok

检查期望的值能否转换成`true`
(true).should.be.ok;

true | True

检查期望的值是否为`true`,不转换
(true).should.be.true;
false.should.not.be.True;

false | False

检查期望的值是否为`false`,不转换
(true).should.not.be.false;
false.should.be.False;

eql

检查期望的值跟真实的值在字面上是否相等,并且深度比较
require('should');

describe('test should.js', function(){
    var foo = {
        foo: 'foo',
        bar: {
            bar: 'bar'
        }
    };
    it('test eql', function(){
        (foo).should.be.eql({
            foo: 'foo',
            bar: {
                bar: 'bar'
            }
        });
    });
});

equal | exactly

检查期望的值与真实的值是一样的,当是比较值类型的话,跟`eql`一样,比较引用类型的话,
则要检查两者是否引用同一地址.
require('should');

describe('test should.js', function(){
    var foo = {
        foo: 'foo',
        bar: {
            bar: 'bar'
        }
    };
    it('test eql', function(){
        (foo).should.not.be.equal({
            foo: 'foo',
            bar: {
                bar: 'bar'
            }
        });
    });
});

throw | throwError

检查期望的函数是否会返回异常,方法参数支持异常信息,正则表达式,对象,以便精确匹配错误信息
(function(){ throw new Error('fail') }).should.throw();
(function(){ throw new Error('fail') }).should.throw('fail');
(function(){ throw new Error('fail') }).should.throw(/fail/);

(function(){ throw new Error('fail') }).should.throw(Error);
var error = new Error();
error.a = 10;
(function(){ throw error; }).should.throw(Error, { a: 10 });
(function(){ throw error; }).should.throw({ a: 10 });

match

检查期望的值与传入的`正则`,`函数`,`对象`进行匹配

匹配规则如下:

  • 如果参数是正则并且期望值是字符串的话,则直接正则匹配字符串即可.
  • 如果参数是正则并且期望值是数组的话,则依次用正则匹配数组元素.
  • 如果参数是正则并且期望值是对象,则依次对对象键值用正则匹配.
  • 如果参数是函数,当函数抛异常或者返回false,则判定为没匹配上.
  • 如果参数是对象,则相同键值用上面的规则来匹配.
  • 其它情况都适为没匹配上.
'foobar'.should.match(/^foo/);
'foobar'.should.not.match(/^bar/);

({ a: 'foo', c: 'barfoo' }).should.match(/foo$/);

['a', 'b', 'c'].should.match(/[a-z]/);

(5).should.not.match(function(n) {
  return n < 0;
});
(5).should.not.match(function(it) {
   it.should.be.an.Array;
});
({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should
.match({ a: 10, b: /c$/, c: function(it) {
   return it.should.have.property('d', 10);
}});

[10, 'abc', { d: 10 }, 0].should
.match({ '0': 10, '1': /c$/, '2': function(it) {
   return it.should.have.property('d', 10);
}});

matchEach

依次对期望值进行匹配

匹配规则如下:

  • 如果参数是正则,则依次对期望值中的对象值或者数组项进行正则匹配
  • 如果参数是函数,当函数抛异常或者返回false,则没匹配上
  • 其它情况,则直接按eql来处理
[ 'a', 'b', 'c'].should.matchEach(/\w+/);
[ 'a', 'a', 'a'].should.matchEach('a');

[ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') });

{ a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') });

Infinity

检查期望的值是否为无穷大或者无穷小
(10).should.not.be.Infinity;
NaN.should.not.be.Infinity;

NaN

检查期望的值是否为NaN
(10).should.not.be.NaN;
NaN.should.be.NaN;

above | greaterThan

检查期望的值是否大于某数
(10).should.be.above(0);
(10).should.not.be.greaterThan(100);

approximately

检查期望的值大约在(某个数±某个半径)内.
// 9.99 10±0.1
(9.99).should.be.approximately(10, 0.1);

below | lessThan

检查期望的值小于某数
(0).should.be.below(10);
(100).should.not.be.lessThan(10);

within

检查期望的值在某两个数之前,包含两个数
(10).should.be.within(10, 20);
(13).should.be.within(10, 15);

empty

检查期望的值是否为空,比如空字符串,空数组,空对象.
''.should.be.empty;
[].should.be.empty;
({}).should.be.empty;

enumerable

检查期望的值是否有可枚举的属性
({ a: 10 }).should.have.enumerable('a');

enumerables

检查期望的值是否有多个可枚举的属性
({ a: 10, b: 10 }).should.have.enumerables('a', 'b');
({ a: 10, b: 10 }).should.have.enumerables(['a', 'b']);

keys | key

检查期望的值是否包含传入的键
({ a: 10 }).should.have.keys('a');
({ a: 10, b: 20 }).should.have.keys('a', 'b');
({ a: 10, b: 20 }).should.have.keys([ 'a', 'b' ]);
({}).should.have.keys();

length | lengthOf

检查期望的值的长度
[1, 2].should.have.length(2);

ownProperty

检查期望的值是否有自己的某个属性
({ a: 10 }).should.have.ownProperty('a');

properties

检查期望的值是否有某些属性,可以批量检查属性
({ a: 10 }).should.have.properties('a');
({ a: 10, b: 20 }).should.have.properties([ 'a' ]);
({ a: 10, b: 20 }).should.have.properties({ b: 20 });

property

检查期望的值是否有某个属性,单个检查
({ a: 10 }).should.have.property('a');
({ a: 10 }).should.have.property('a', 10);

propertyByPath

根据传入的参数深度来获取属性的值
({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10);

propertyWithDescriptor

检查期望的值的属性有某些描述
({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true });

startWith

检查字符串是否以某个传入的参数开头
'abc'.should.startWith('a');

endWith

检查字符串是否以某个传入的参数结尾
'abc'.should.endWith('c');

instanceof | instanceOf

检查期望的值是否是某个类的实例
'abc'.should.be.instanceof(String);

type

检查期望的值是否是某个类型
'abc'.should.be.type('string');

null | Null

检查期望的值是否为null
var should = require('should');
describe('test should.js ', function(){
    it('test null ', function(){
        should(null).be.null;
    });
});

undefined | Undefined

检查期望的值是否undefined
var should = require('should');
describe('test should.js ', function(){
    it('test undefined', function(){
        var a;
        should(a).be.undefined;
    });
});

上面是一些常用的should.js中的断言方法,下面简单的说下mocha测试框架的用法

异步处理与前后注入

jasmine类似,也是通过在it,beforeEach里传入done来确定是否执行完成

describe('test should.js', function(){

    var foo = 0;

    before('首次调用',function(done){
        setTimeout(function(){
            foo += 1;
            done()
        }, 1000);
    });
    beforeEach(function(done){
        setTimeout(function(){
            foo += 1;
            done();
        }, 1000);
    })
    afterEach(function(){
        foo = 0;
    });
    it('test beforeEach', function(done){
        setTimeout(function(){
            (foo).should.eql(2);
            done();
        }, 1000);
    })


});

禁用与开启测试

  • .only可以让某个it执行而忽略别的it
describe('1.test mocha', function(){

    it.only('test .only', function(){
        '123'.should.be.String;
    });

    // 下面的spec不会执行
    it('ignore invoke', function(){
        (0).should.be.eql(0);
    });
});
  • .skip可以禁止某个it而执行别的it
describe('test mocha', function(){

    // 下面的spec不会执行
    it.skip('ignore spec', function(){
        ({}).should.be.Object;
    });

    it('test .skip', function(){
        ({}).should.be.empty;
    });

});

自由切换bdd,tdd,exports模式

mocha -u [bdd | tdd | exports] *.js

-u选项支持传递要使用的测试类型,默认是bdd,可以选择tdd,exports

BDD

bdd用的比较多,jasmine的测试风格就是bdd,它的特征就是使用describe,it

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

  describe('#indexOf()', function(){
    it('should return -1 when not present', function(){
      [1,2,3].indexOf(4).should.equal(-1);
    });
  });
});

TDD

tddbdd区别在于,它使用suite,test,suiteSetup,suiteTeardown,setup,teardown

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

      suite('#indexOf()', function(){
            test('should return -1 when not present', function(){
                ([1,2,3].indexOf(4)).should.be.eql(-1);
            });
      });
});

Exports

exports类似于node里的模块语法,before, after, beforeEach, and afterEach是作为对象的属性来处理,其它对象的值默认是suite,属性是函数的话,代表是一个test

module.exports = {
      before: function(){
            // ...
      },

      'Array': {
            '#indexOf()': {
              'should return -1 when not present': function(){
                [1,2,3].indexOf(4).should.equal(-1);
              }
            }
      }
};

其实的测试风格还有QUnit,Require,更多详情请点击这里.

自由切换输出风格

目前默认的输出格式为spec,可以通用-R spec来指定,目前已有的格式有dot,nyan,tap,list,progress,json,min,doc,markdown等,html格式只在浏览器中有效

mocha细节问题

  • 设置测试组超时时间,可以在describe或者suite代码块里调用this.timeout方法
describe('a suite of tests', function(){
    this.timeout(500);

    it('should take less than 500ms', function(done){
        setTimeout(done, 300);
    })

    it('should take less than 500ms as well', function(done){
        setTimeout(done, 200);
    })
})
  • 设置测试用例超时时间,可以在it或者test代码块里调用this.timeout方法
it('should take less than 500ms', function(done){
  this.timeout(500);
  setTimeout(done, 300);
})
  • mocha默认会执行./test/*.js里的测试文件,所以这个目录是放测试文件的好地方
  • 为了方便执行mocha命令,可以建立一个makefile文件,如下
test:
    ./node_modules/.bin/mocha --reporter list

.PHONY: test

下次运行的话,直接在终端上输入make test

总结

mocha是一个功能比较丰富的测试框架,希望更多的前端工作者们能用上它.


目录
相关文章
|
Go 数据库
Golang 语言编写 gRPC 实战项目
Golang 语言编写 gRPC 实战项目
169 0
|
NoSQL MongoDB 数据库
DeprecationWarning: count is deprecated. Use Collection.count_documents instead
当我使用pymongo查询出对应的cursor(find出的document的迭代器),然后查看查询出数据的数量时使用如下代码: ```python db = MongoClient(host='192.168.1.3', port=27017) # dbname为操作的数据库名称,collectionname为操作的集合名称
395 0
|
8月前
|
Oracle 关系型数据库 MySQL
【实操记录】MySQL二进制安装包部署
本文详细描述了采用二进制安装的各个步骤,具有较强的参考意义,基本可作为标准步骤实施
378 0
|
7月前
|
存储 缓存 监控
Elasticsearch Filter 缓存加速检索的细节,你知道吗?
【8月更文挑战第15天】在大数据与搜索引擎的广阔天地里,Elasticsearch 凭借其强大的全文搜索能力和可扩展性,成为了众多企业和开发者的首选。而在Elasticsearch的性能优化中,Filter缓存(也称为Filter Cache,自Elasticsearch 7.x版本后更名为Query Cache的一部分)扮演着至关重要的角色。今天,我们就来深入探讨一下Elasticsearch Filter缓存如何加速检索过程,以及在日常工作学习中如何有效利用这一特性。
132 0
|
JavaScript CDN
JS:NPM发布一个Vue组件UI库并使用CDN引入使用
JS:NPM发布一个Vue组件UI库并使用CDN引入使用
628 0
|
小程序 Java 索引
|
存储 SQL Java
基于二进制控制系统权限
在数学和数字电路中指以2为基数的记数系统,以2为基数代表系统是二进位制的。这一系统中,通常用两个不同的数字0和1来表示。在计算机中,最常用的是二进制,因为组成计算机系统的逻辑电路通常只有开和关这两个状态,用0和1很好表示这两种状态。
2578 0
基于二进制控制系统权限
|
6月前
|
移动开发 JavaScript 前端开发
HTML5 Audio(音频)详解
HTML5 通过 `&lt;audio&gt;` 标签简化了网页音频嵌入。本文详细介绍其基本语法与常用属性(如 `controls`、`autoplay`),并通过示例代码展示如何使用 JavaScript 控制音频播放及处理音频事件。此外,还提供了关于浏览器兼容性、自适应设计及无障碍访问的注意事项,助您优化音频体验。
|
8月前
|
存储 数据安全/隐私保护 Python
`zxcvbn`是一个用于密码强度估计的开源库,由Dropbox开发。它基于一系列启发式方法,包括密码字典、常见密码模式、键盘布局等,来评估密码的强度。
`zxcvbn`是一个用于密码强度估计的开源库,由Dropbox开发。它基于一系列启发式方法,包括密码字典、常见密码模式、键盘布局等,来评估密码的强度。
|
存储 JavaScript 前端开发
5分钟快速搭建一个vue3+ts+vite+pinia项目
最近接到一个新的需求,需要使用Vue3来开发,本着学习的目的,就先来创建一个Vue3项目。既然是学习,那就怎么新怎么来。
3224 2
5分钟快速搭建一个vue3+ts+vite+pinia项目