资讯专栏INFORMATION COLUMN

探知JS测试(2)

TZLLOG / 2385人阅读

摘要:针对于类型已经出啦个方法来判断在各种库里,也出现了想等语义判断。在断言库里,类型判断也是必不可少的一部分。测试用例应该会。在下一个测试套件内,还是依照默认值。

前一篇文章,我们已经简单的阐述了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。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78674.html

相关文章

  • 探知JS测试(1)

    摘要:单元测试这是测试类型的一种,所谓的单元即,由一些函数组成能完成某项功能的模块。单元测试的过程想好测试用例动手写测试查看测试结果,通过则否则应该进行测试模式想说一下,测试模式和单元测试的区别。测试模式包括单元测试通常测试模式有和模式。 有一定水平的js童鞋,应该会经常看到一些书上,在介绍项目的时候,会不由自主说道测试。 比如,单元测试,函数测试,或是TDD,BDD等测试模式。没错,这也是...

    xingpingz 评论0 收藏0
  • 探知JS测试(1)

    摘要:单元测试这是测试类型的一种,所谓的单元即,由一些函数组成能完成某项功能的模块。单元测试的过程想好测试用例动手写测试查看测试结果,通过则否则应该进行测试模式想说一下,测试模式和单元测试的区别。测试模式包括单元测试通常测试模式有和模式。 有一定水平的js童鞋,应该会经常看到一些书上,在介绍项目的时候,会不由自主说道测试。 比如,单元测试,函数测试,或是TDD,BDD等测试模式。没错,这也是...

    bladefury 评论0 收藏0
  • 探知js测试(3)

    摘要:模块测试模块语法我这里提及一点。基本工程目录一个良好的工程目录,能够帮助你测试成本降到最低。这一块算是独立于单元测试的。 前面两篇已经把,js测试的模式,框架,断言库基本介绍了一遍。这里,我们要上升到整体测试架构上来.首先,单元测试的对象是模块,这里我们就要将自己测试目标调整到对模块测试上来。所以,这里我们需要使用CommonJS或者es6的模块的写法了。另外需要了解,mocha框架测...

    陈江龙 评论0 收藏0
  • 探知js测试(3)

    摘要:模块测试模块语法我这里提及一点。基本工程目录一个良好的工程目录,能够帮助你测试成本降到最低。这一块算是独立于单元测试的。 前面两篇已经把,js测试的模式,框架,断言库基本介绍了一遍。这里,我们要上升到整体测试架构上来.首先,单元测试的对象是模块,这里我们就要将自己测试目标调整到对模块测试上来。所以,这里我们需要使用CommonJS或者es6的模块的写法了。另外需要了解,mocha框架测...

    pakolagij 评论0 收藏0
  • 探知JS测试(2)

    摘要:针对于类型已经出啦个方法来判断在各种库里,也出现了想等语义判断。在断言库里,类型判断也是必不可少的一部分。测试用例应该会。在下一个测试套件内,还是依照默认值。 前一篇文章,我们已经简单的阐述了BDD,TDD以及mocha测试框架,chai断言库. 这里我们将进一步深入,比较全部的了解测试的API。前文,我们已经知道了,BDD本身可以比拟为文章的骨架,而chai断言库就是骨架里面的血管和...

    jonh_felix 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<