如何用Qunit测试你的javascript代码Word文件下载.docx
《如何用Qunit测试你的javascript代码Word文件下载.docx》由会员分享,可在线阅读,更多相关《如何用Qunit测试你的javascript代码Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。
即使你这么做,这还需要一段时间才能弄清楚你的问题是由回归引起的。
使用单元测试,你写测试用例去发现缺陷,一旦代码被修改,您通过测试再筛选一次。
一旦出现回归,一些测试用例一定会失败,你可以很容易地认出他们,知道哪部分代码包含了错误。
既然你知道你刚才修改了什么,就可以很容易地解决问题。
单元测试的另外一个尤其是对于Web开发的优点:
让跨浏览器兼容性测试变得更容易。
仅仅在不同浏览器中运行你的测试用例,一旦某个浏览器出现问题,修复它并重新运行这些测试用例,确保不会在别的浏览器引起回归,一旦全部通过测试,就可以肯定的说,所有的目标浏览器都支持。
我喜欢提及一个JohnResig的项目:
TestSwarm。
TestSwarm通过分发,将JavaScript单元测试带到了一个新的层次。
这是一个包含很多测试用例的网站,任何人都可以去那运行一些测试用例,然后返回结果会返回到服务器。
通过这种方式,代码会非常迅速的在不同的浏览器进行测试,甚至不同的平台运行。
怎么用QUnit编写测试用例
如何正确地用QUnit写单元测试呢?
首先,您需要搭建一个测试环境:
<
!
DOCTYPEhtml>
html>
head>
<
title>
QUnitTestSuite<
/title>
linkrel="
stylesheet"
href="
mce_href="
type="
text/css"
media="
screen"
>
scripttype="
text/javascript"
src="
mce_src="
--Yourprojectfilegoeshere-->
myProject.js"
/script>
--Yourtestsfilegoeshere-->
myTests.js"
/head>
body>
h1id="
qunit-header"
/h1>
h2id="
qunit-banner"
/h2>
divid="
qunit-testrunner-toolbar"
/div>
qunit-userAgent"
olid="
qunit-tests"
/ol>
/body>
/html>
正如你所见,在这里使用了一个被托管的QUnit框架版本。
将要被测试的代码需要添加到myProject.js中,并且你的测试用例应该插入到myTest.js。
要运行这些测试,只需在一个浏览器中打开这个html文件。
现在需要写一些测试用例了。
单元测试的基石是断言。
“断言是一个命题,预测你的代码的返回结果。
如果预测是假的,断言失败,你就知道出了问题。
”
运行断言,需要把它们放入测试用例中:
//Let'
stestthisfunction,用于被测试的Javascript代码放在myProject.js文件中
functionisEven(val){
returnval%2===0;
}
//所编写的测试用例代码放在myTests.js文件中
test('
isEven()'
function(){
ok(isEven(0),'
Zeroisanevennumber'
);
ok(isEven
(2),'
Soistwo'
ok(isEven(-4),'
Soisnegativefour'
ok(!
isEven
(1),'
Oneisnotanevennumber'
isEven(-7),'
Neitherisnegativeseven'
})
注:
也可将所要测试的代码与测试用例放在同一个js文件中
这里,我们定义一个函数:
isEven,用来检测一个数字是否为奇数,并且我们希望测试这个函数来确认它不会返回错误答案。
我们首先调用test(),它构建了一个测试用例;
第一个参数是一个将被显示在结果中的字符串,第二个参数是包括我们断主的一个回调函数。
我们写了5个断言,所有的都是布尔型的。
一个布尔型的断言,期望它的第一个参数为true。
第二个参数依然是要显示在结果中的消息。
下面是你想要得到的,只要你运行测试用例:
由于所有的断言都已成功通过,我们可以高兴的认为isEven()工作正常。
让我们看看如果一个断言失败了会发生什么。
stestthisfunction
function(){
Neitherdoesnegativeseven'
//Fails
ok(isEven(3),'
Threeisanevennumber'
下面是结果:
该断言失败因为我们故意把它写错,但是在你的项目中,如果测试未通过,并且所有的断言都是正确的,你将发现一个bug。
更多断言
ok()不仅是QUnit提供的唯一断言,当在测试你的项目时,还会有一些非常有用的其他类型的断言:
比较断言
比较断言,equals(),期望它的第一个参数(是实际值)等于它的第二个参数(期望值)。
它很类似于ok(),但均会输入实现和期望值,使得高度更加简单,像ok()一样,它可带一个可选的第三个参数作为显示的消息。
所以可以代替:
assertions'
ok(1==1,'
oneequalsone'
你可以这样写:
equals(1,1,'
注意最后一个“1”,这是比较值
如果两个值不相等:
equals(2,1,'
提供更多些信息,让生活更简单些。
比较断言使用“==”来比较它的参数,所以它不能处理数组或对象的比较:
test'
equals({},{},'
fails,thesearedifferentobjects'
equals({a:
1},{a:
1},'
fails'
equals([],[],'
fails,therearedifferentarrays'
equals([1],[1],'
为了测试这种相等,QUnit提供了另外一种断言:
恒等断言
。
恒等断言,same(),期望相同的参数相等,但是它较深的采用递归比较断言,不仅作用于原始类型,而且包括数组和对象。
断言,在前面的例子中,如果你把他们改成恒等断言将全部通过。
same({},{},'
passes,objectshavethesamecontent'
same({a:
passes'
same([],[],'
passes,arrayshavethesamecontent'
same([1],[1],'
注意same()使用”===”去比较,如有必要的话,所以它在比较特殊值的时候就派上用场了。
equals(0,false,'
true'
same(0,false,'
false'
equals(null,undefined,'
same(null,undefined,'
结构化你的断言
把所有的断言放在一个单独的测试案例中是相当不好的想法,因为这很难去维护,并且不能返回一个纯净的结果。
你需要做的就是结构化他们,把他们放在不同的测试案例,每个目标为一个单独功能。
甚至可以通过调用模块函数来把测试案例组织到不同的模块:
module('
ModuleA'
atest'
function(){});
ananothertest'
ModuleB'
异步测试
在前面的示例中,所有的断言都是同步调用的,这意味着他们是一个接着一个运行的。
在这个真实的世界,同样存在着很多异步的函数,例如Ajax请求或通过setTimeout()或sestInterval()调用的方法。
我们如何去测试这些种类的方法呢?
QUnit提供了一个特殊的叫做和“异步测试”的测试案例,提供给异步的测试:
让我们首先尝试用常规的方法写:
asynchronoustest'
setTimeout(function(){
ok(true);
},100)
})
看到了?
这就好像我们没有写任何断言一样。
这是因为断言是被异步执行的,到它被调用的时候,此次测试已经执行完成。
这是正确的版本:
//Pausethetestfirst
stop();
setTimeout(function(){
//Aftertheassertionhasbeencalled,
//continuethetest
start();
},100)
在这,我们使用了stop()去暂停此次测试案例,并且在断言被调用以后,我们使用start()继续。
在调用完test()后立即调用stop()是很平常的;
所以QUnit提供了一个捷径:
asyncTest()。
你可以像这样重写之前的示例:
asyncTest('
//Thetestisautomaticallypaused
//Aftertheassertionhasbeencalled,
//continuethetest
还有一点要注意:
setTimeout()通常会调用它自己的回调函数,但如果它是一个自定义的函数(例如:
一个Ajax调用)。
你如何确认回调函数被调用了呢?
并且如果回调函数没有被调用,start()将不会被执行,整个单元测试将被挂起:
所以这就是你需要做的:
//Acustomfunction
functionajax(successCallback){
$.ajax({
url:
'
server.php'
success:
successCallback
});
}
//Pausethetest,andfailitifstart()isn'
tcalledafteronesecond
stop(1000);
ajax(function(){
//...asynchronousassertions
})
你可以通过延时去stop(),它告知QUnit,“如果start()在延时后没有被调用,你应未通过测试”。
你可以确认的是整个测试没有挂起而且如果哪里出了问题你可以注意到。
那么多个异步函数呢?
你在哪里放置start()?
可把它放在setTimeout()里:
//Pausethetest
},2000);
延时应该适当的长足够来允许二者的回调函数在测试继续执行前被调用。
但是如果其中一个回调函数没有被调用怎么办?
你怎样去知道?
这就是expect()加入的原因:
//TellQUnitthatyouexpectthreeassertionstorun
expect(3);
你给expect()传一个数字告知QUnit你期望X个断言去执行,如果一个断言未被执行,这个数字将不会匹配,而且你瘵会注意到有些东西出错了。
这仍有一个expect()的捷径:
你只需给test()或asyncTest()的第二个参数传递一个数字:
//TellQUnitthatyouexpectthreeassertiontorun
3,function(){