探知JS测试(2)

前一篇文章,我们已简朴的论述了BDD,TDD以及mocha测试框架,chai断言库. 这里我们将进一步深切,比较悉数的相识测试的API。
前文,我们已晓得了,BDD自身可以比拟为文章的骨架,而chai断言库就是骨架内里的血管和肌肉(脂肪). 二者连系才写出一片圆满的测试文章。 这里,我们先看一下脂肪是怎样炼成的。

expect断言

这里我针对expect断言举行一些解说,顺便把一些比较重要的API,梳理一遍。
逻辑指导语法:

not
deep
any
all
and

not

取非语法

expect(1).to.not.equal(2); //pass

deep

深层搜检,该重要针关于对象和数组范例。 就比如复制一样,分为深复制和浅复制. 一般状况下,我们直接比较的都是浅层.
像如许的

//浅层比较
var expect = require('chai').expect;
var test1 = {
    foo:{
        bar:1
    }
}
var test2 = {
    bar:1
}
describe('Counter',function(){
    it('test',()=>{
        expect(test1.foo).to.equal(test2);
    })
})
//fail
//运用深层比较
describe('Test',function(){
    it('test',()=>{
        expect(test1.foo).to.deep.equal(test2);
    })
})
//pass

any

按一般语法看,这里就是恣意的意义。一般搭配keys一同运用,用来示意或的意义。

expect(test1).to.have.any.keys('foo','bar');

all

这个语法和”any”的运用也差不多,也是用来示意keys的包括状况

//test1对象的一切keys只要foo和bar
expect(test1).to.have.all.keys('foo',"bar");

上面的逻辑语法一般和动词语法一同运用.
常常使用的动词语法有:

equal
include (alias: contain)
satisfy
match
change

一般,我们运用这里动词连系名词来表达一个状况

equal

望文生义就是相称的意义呗。直接看一下demo

expect(1).to.equal(1);  //相称
expect(2).to.not.equal(3);  //不相称

include

包括的意义,实在他的alias另有contains,includes。 不过表达的都是一样的意义,所以引荐直接运用include就可以了。include常常和array,string,以及object运用. 正关于这3种范例,《包括》意味着:

array: 查询是不是包括子项
string: 查询是不是包括子字符串
object: 查询是不是包括子对象
//查询array是不是包括子项
expect([1,2,3,4,5]).to.include(3);
//包括sting的子串
expect("good").to.include("oo");
//推断对象是不是包括子对象
expect({first:1,second:2}).to.include({second:2})

还记得上文提到的have吗? 实在,这个和include是有区分的。 一般而言,have一般是和keys举行搭配的.

expect({first:1,second:2}).to.have.any.keys("first");
//等价于
expect({first:1,second:2}).to.include.keys("first");

别的,have自身自带all的效果,所以以为”all”一般是和include一同搭配.

expect({first:1,second:2}).to.have.keys("first","second");
//等价于
expect({first:1,second:2}).to.have.all.keys("first","second");
//等价于
expect({first:1,second:2}).to.include.all.keys("first","second");

satisfy

这个应当可以算是一个全能assertion. 他的参数是一个函数,接收的参数就是expect内里的内容。 而且该函数的返回值必需是Boolean. 假如你的返回值没有的话,那末该case是不会经由过程的。

expect({first:1,second:2}).to.satisfy(function(obj){
            return obj.first===1;
        }); 
        //pass

虽然是全能的,然则尽力不引荐运用,因为是在是太好用了,而形成的problem就是你的测试用例不清楚,没有很好的可读性。要晓得断言库的涌现就是让你的测试用例可以像文章一样具有优越的可读性.

match

这个要领实在和string.match是比较类似的。他们都是用来检测字符串范例,是不是满足正则的测试。

expect("good").to.match(/(oo){1}/);
//pass

change

用来表征一个对象的值是不是被一个函数所转变.

get to the point

//测试对象
var test2 = {
    bar:1
}
function changeValue(){
    test2.bar=2;
}
//测试用例
expect(changeValue).to.change(test2,"bar");

事实上,这个真的没有什么卵用。用的频次照样蛮低的。
Okkkkay~
在断言中另有最重要的一部分,关于number的推断.
常常使用的number推断有:

above(alias: gt)
below(alias: lt)
least(alias: gte)
most(alias: lte)
within

above

above等价于greater than(>=). 然则above能更好的表达语义,所以这里就运用above.

expect(2).to.above(1);

below

同理below和above类似. below等价于less than(<=)

expect(2).to.not.below(1);
expect(2).to.below(3);

least

在中文意译就为最少为若干~ 翻译为数学言语就是 (>=) . 这里,我们须要明白一个观点,即,测试用例应当给你最直观的感觉, 我们的用例是给normal people看的,而不是特指针关于数学家,或许程序员看的。
运用最好语义化的表达就是最重要的.

expect(num).to.least(1); //翻译一遍就是: num最少为1

most

和least类似。我这里就不举例论证了。

expect(num).to.most(12); //num最多为12

within

标识一个数的range. 相当于,数学上的 “[num1,num2]”. 推断你的expect是不是在这个区间内。

expect(1).to.within(1,2); //pass

关于Number这一块内容我们差不多梳理完了。
是不是是很死板呀~
恩~ 我也这么以为
下面,我们再来看一点死板的东西呗。 破罐子破摔
范例推断
要晓得,在js中,范例推断是最奇葩的一个。 针关于范例js已出啦3个要领来推断》 instanceof typeof constructor. 在种种库里,也涌现了想isArray,isBoolean,isArrayLike等语义API推断。 在断言库里,范例推断也是必不可少的一部分。

instanceof
ok
false
true
null
undefined
exist
empty

instanceof

和constructor范例推断类似。 用来推断一个对象的本来组织函数是谁。

function changeValue(){}
var test1 = new changeValue();
describe('Test',function(){
    it('test',()=>{
        expect(test1).to.be.instanceof(changeValue);
    })
})

ok/true/exist

上述3个语法的关联应当是:exist>ok>true.
因为3者类似,这里就一同说清楚明了。
exist就是用来推断一个值是不是存在,即,既不是null也不是undefined.
而,ok是用来推断一个值是不是ok(别打我~). 即,该值既不是null,也不是undefined,更不是false
true就很简朴,只要true才pass. 相当于”===”的效果.
详看demo:

//exist->pass
expect("exist").to.exist;
expect(null).to.not.exist;
expect(undefined).to.not.exist;
expect(false).to.exist;
//ok->pass
expect("exist").to.be.ok;
expect(null).to.not.be.ok;
expect(undefined).to.not.be.ok;
expect(false).to.not.be.ok; //关于上面的exist
//true->pass
expect(true).to.be.true;
expect(1).to.not.be.true;

false/null/undefined/empty

这些都是推断一个内容是不是不满足时而造出来语法.
看字面情势可以晓得,他们离别对应于本身的范例。
false->false
null->null
undefined->undefined
而,empty则是推断expect的length是不是为0. 固然针关于没有length属性的范例。测试用例应当会die。

expect('').to.be.empty;
expect(12).to.not.be.empty;

到这里,expect的断言库,差不多就这些了。 假如人人另有种想要进修的激动,可以去mocha官网上进修(仔细脸)

BDD分外语法

上篇引见了describe的一些基础语法,然则彷佛照样纰漏了一些,比较高等的API。
一个为only.一个为skip.另有一个为done

only

only要领示意在一个block内,只运转该用例的测试。它一般在你满屏输出毛病的时刻,举行离开修正bug而运用的. 可以在it或许describe上面运用

describe('Test',function(){
    it.only('test',()=>{
        expect(1).to.equal(1);
    });
    it("it will output error",function(){
        expect(2).to.equal(3);
    })
})
//在命令行测试会直接pass。 因为第二个测试用例并没有实行

skip

该要领,用来跳过某个测试用例。 同样在一般状况下,我们不会运用这个API。 它的运用状况依然是,调试你在一个Block里,写出很多个测试时,才会运用.

describe('Test',function(){
    it('test',()=>{
        expect(1).to.equal(1);
    });
    it.skip("it will output error",function(){
        expect(2).to.equal(3);
    })
})
//第一个会提醒pass
//第二个会提醒pending

done

这个应当是为js量身打造的.因为js自身就是一门异步言语,而mocha没法污染异步的API,所以这个done就是给我们手动去检测异步完毕而设立的。
来个栗子:

//没有异步效果,效果会直接输出I'm testing,而I've finished test却没有效果
describe('Test',function(){
    it('test',()=>{
        console.log("I'm testing")
        setTimeout(function(){
            console.log("I've finished test");
        },200);
    });
})
//这里我们须要加上一个异步的flag--done
describe('Test',function(){
    it('test',(done)=>{  //这里加上一个done的参数,示意这是个异步的测试用例
        console.log("I'm testing")
        setTimeout(function(){
            console.log("I've finished test");
            done();  //这里手动通知mocha我已测试完了
        },200);
    });
});
输出的效果为:
//I'm testing
//I've finished test

而,大部分时刻,异步测试并非去测试setTimeout(are u **?). 最重要测试异步的应当是Promise或许是$.Deferred。不过es6近来盛行,我们一样以Promise作为例子,Deferred的道理和Promise是一样的.

异步测试Promise

测试Promise的时刻,我们固然可以运用上述的done要领来mark一下.

describe('Test',function(){
    before(function(){
        console.log("I'm testing");
    })
    it('test',(done)=>{
        "use strict";
        new Promise(function(resolve,reject){
            setTimeout(()=>{
                resolve("ok");
            }, 200)
        })
        .then(function(){
            console.log("I've finished the test");
            done();
        })
    });
});
//一般状况会输出: 标识胜利
// I'm testing
//I've finished the test

然则须要注重的是,假如你的异步实行时候太长,mocha是不会wait u的。 mocha默许的最低时候是2s。所以,假如你的异步时候超出了。像如许:

    new Promise(function(resolve,reject){
            setTimeout(()=>{
                resolve("ok");
            }, 2000)
        })
        .then(function(){
            console.log("I've finished the test");
            done();
        })

他会直接爆出如许的毛病.

 Error: timeout of 2000ms exceeded

固然,假如你想转变他的默许值设置也可以。
想如许设置就over了

mocha -t 10000

或许直接测试用例中零丁设置:

describe('Test',function(){
    this.timeout(100);
    before(function(){
        console.log("I'm testing");
    });
    it('test',(done)=>{
        "use strict";
        new Promise(function(resolve,reject){
            setTimeout(()=>{
                resolve("ok");
            }, 2000)
        })
        .then(function(){
            console.log("I've finished the test");
            done();
        })
    });
});
//因为你的时候设置太短,所以会涌现上述一样的毛病

这里的this.timeout只能影响到,当前的测试套件。 鄙人一个测试套件内,照样遵照默许值2000ms。

    原文作者:villainhr
    原文地址: https://segmentfault.com/a/1190000004431086
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞