JavaScript的单元测试工具.docx
- 文档编号:18423564
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:16
- 大小:110.79KB
JavaScript的单元测试工具.docx
《JavaScript的单元测试工具.docx》由会员分享,可在线阅读,更多相关《JavaScript的单元测试工具.docx(16页珍藏版)》请在冰点文库上搜索。
JavaScript的单元测试工具
摘要:
一些开发者可能会抱怨说JavaScript难以测试,然而,随着当前对Web应用客户端重视程度的增加,JavaScript代码的单元测试正在变得越来越重要。
导读:
一些开发者可能会抱怨说JavaScript难以测试,然而,随着当前对Web应用客户端重视程度的增加,JavaScript代码的单元测试正在变得越来越重要。
现在,你已有了一些可用来确保代码坚固性的工具,在本文中了解一些最常见的JavaScript单元测试工具:
QUnit、YUITest和JSTestDriver,代码例子会为你分步讲解一些示范性的测试用例。
引言
单元测试致力于验证一个模块或一个代码单元是按照设计或是如预期那样运作的。
一些开发者宁愿花时间来实现一些新的模块,却把编写测试用例看成是浪费时间的事情。
然而,在应付大型应用时,单元测试实际上是节省了时间;其帮助你追踪问题,让你能够安全地进行代码更新。
在过去,单元测试只是应用在服务器端语言上。
但是,随着前端组件中的复杂性的不断提升,编写JavaScript代码的测试单元的这种需要就增加了。
如果你通常都不为客户端脚本编写测试代码的话,则学习曲线可能会很陡峭,对用户界面的测试可能会要求你调整一下思维过程。
(而且,一些开发者可能一时还难以认可JavaScript是一种正式的编程语言)。
JavaScript单元测试
为了说明JavaScript的测试,本节内容分析了一个用JavaScript编写的基本函数的测试用例。
清单1给出了要测试的函数:
把(数值)3和传递进来的变量相加。
清单1.源代码(example1/script.js)
1functionaddThreeToNumber(el){
2returnel+3;
3}
清单2把测试用例包含在一个自执行函数中。
清单2.测试用例(example1/test.js)
4(functiontestAddThreeToNumber(){
5vara=5,
6valueExpected=8;
7
8if(addThreeToNumber(a)===valueExpected){
9console.log("Passed!
");
10}else{
11console.log("Failed!
");
12}
13})();
在把5传入到被测试的函数中之后,测试检查其返回值是8,如果测试成功的话,在某个现代浏览器的控制台中输出Passed!
,否则输出的是Failed!
。
为了运行这一测试,你需要:
1.在某个充当测试运行器的HTML页面中导入两个脚本文件,如清单3所示。
2.在浏览器中打开该页面。
清单3.HTML页面(example1/runner.html)
14
DOCTYPEhtml>
15
16
17
18
19
20
21
22
23
一种替代使用浏览器控制台的做法是,在页面中或是在由alert()方法生成的弹出窗口中输出结果。
断言(assertion),测试用例中的核心要素,被用来验证某个条件的满足。
例如,在清单2中,addThreeToNumber(a)===valueExpected就是一个断言。
如果大量的测试用例都有很多断言的话,框架就派上用场了,接下来的几节内容重点说明一些最受欢迎的JavaScript单元测试框架:
QUnit、YUITest和JSTestDriver。
QUnit入门
QUnit是一个类似于JUnit(Java编程)的单元测试框架,其被JQuery团队用来测试jQuery库。
若要使用QUnit,你需要:
1.下载qunit.css和qunit.js文件(参见参考资料)。
2.创建一个HTML页面,该页面包含了一些导入你刚下载的那些CSS和JavsScript文件的特定标签。
清单4给出了QUnit的一个标准的HTML运行器。
清单4.HTML运行器(qunit/runner.html)
24
DOCTYPEhtml>
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
假设你有两个函数负责摄氏温度到华氏温度的来回转换,清单5给出了进行这些转换的脚本。
清单5.转换(qunit/js/script.js)
41functionconvertFromCelsiusToFahrenheit(c){
42varf=c*(9/5)+32;
43returnf;
44}
45
46functionconvertFromFahrenheitToCelsius(f){
47varc=(f-32)*(5/9);
48returnc;
49}
清单6给出了其各自的测试用例。
清单6.测试用例(qunit/js/test.js)
50module("Temperatureconversion")
51
52test("conversiontoF",function(){
53varactual1=convertFromCelsiusToFahrenheit(20);
54equal(actual1,68,?
Valuenotcorrect?
);
55
56varactual2=convertFromCelsiusToFahrenheit(30);
57equal(actual2,86,?
Valuenotcorrect?
);
58})
59
60test("conversiontoC",function(){
61varactual1=convertFromFahrenheitToCelsius(68);
62equal(actual1,20,?
Valuenotcorrect?
);
63
64varactual2=convertFromFahrenheitToCelsius(86);
65equal(actual2,30,?
Valuenotcorrect?
);
66})
QUnit中的测试用例由test()方法来定义,逻辑包含在传递给该函数的第二个参数中。
在清单6中,这两个测试被分别命名为conversiontoF和conversiontoC。
每个测试都包含了两个断言,这些用在测试中的断言利用了equal()方法,equal()函数让你比较预期的值和被测试的函数返回的实际值。
equal()方法中的第三个参数是在失败情况下显示的信息。
还可以通过module()函数来把一些测试组织成模块。
在清单6中,模块Temperatureconversion拥有两个测试。
若要运行这些测试:
1.把源代码和测试文件放入到HTML测试器中,如清单7所示.
2.在浏览器中打开该HTML页面。
清单7.在运行器中包含script.js和test.js
67...
68
69
70...
71
图1展示了QUnit在浏览器(Firefox)中显示结果的方式。
图1.QUnit结果
清单6中的断言使用了equal()方法,但这不是QUnit唯一提供的断言,QUnit提供的其他一些断言包括了ok()和strictEqual()。
清单8给出了这些方法的运用方式。
清单8.更多的断言
72module("Otherassertion");
73test("assertions",function(){
74ok(true);
75ok(3);
76strictEqual("c","c");
77equal(3,"3");
78});
ok()函数检查第一个参数为true;strictEqual()验证第一个参数与第二个严格相等。
幕后实情是,strictEqual()使用了===运算符,而equal()使用的是==运算符。
如果测试失败的话,QUnit也会提供一些有用的信息。
把清单8中的代码修改成清单9中的代码,故最后的一个断言会失败。
清单9.最后一个断言出现错误
79module("Otherassertion");
80test("assertions",function(){
81ok(true);
82ok(3);
83strictEqual("c","c");
84strictEqual(3,"3");
85});
图2展示了清单9中的代码的QUnit返回结果。
图2.QUnit结果——最后一个测试失败
结果描述得相当详细,且很容易就跟踪到最后一个断言中的预期结果和实际结果之间的不同。
QUnit的另一个很重要的特性是,其允许你在某个模块中的所有测试被执行之前先、或之后再执行一些命令。
module()函数把setup()和teardown()回调当成第二参数来接收,使用setup()函数来更新清单6,如清单10所示。
清单10.setup()(qunit/js/test-setup.js)
86module("Temperatureconversion",{
87setup:
function(){
88this.celsius1=20;
89this.celsius2=30;
90
91this.fahrenheit1=68;
92this.fahrenheit2=86;
93}
94});
95test("conversiontoF",function(){
96varactual1=convertFromCelsiusToFahrenheit(this.celsius1);
97equal(actual1,this.fahrenheit1);
98
99varactual2=convertFromCelsiusToFahrenheit(this.celsius2);
100equal(actual2,this.fahrenheit2);
101});
102test("conversiontoC",function(){
103varactual1=convertFromFahrenheitToCelsius(this.fahrenheit1);
104equal(actual1,this.celsius1);
105
106varactual2=convertFromFahrenheitToCelsius(this.fahrenheit2);
107equal(actual2,this.celsius2);
108});
该例子把用在断言中的值移到了setup这部分内容中,避免在测试逻辑中使用这些值。
QUnit还通过asyncTest()函数来提供异步测试支持,如果你正在使用AsynchronousJavaScriptandXML(Ajax)来进行事务处理的话,则这是一个非常有用的功能。
在这一上下文中,expect()函数能够让你轻松地验证运行在一个测试中的多个断言。
YUITest:
一个独立的单元测试模块
YUITest,YUI库(Yahoo!
)内部的一个组件,是一个详尽完整的单元测试框架。
若要开始使用YUITest,你需要:
1.把YUI种子导入HTML运行器中,如下.
109
正如该行代码所反映的那样,例子使用的是YUITest的版本3。
在测试脚本文件中,实例化YUI函数,载入所需的模块test和console,如清单11所示。
清单11.载入test和console这两个YUI模块
110
111YUI().use("test","console",function(Y){
112//测试用例放在这里
113});
test模块显然是出于测试目的必需的,console模块则不是强制要用的,不过该例子会使用它来输出结果。
测试用例会放在回调的内部,使用一个全局的Y实例来作为参数。
YUITest使用Y.Test.Case()构造函数来实例化一个新的测试用例,以及使用Y.Test.Suite()构造函数来实例化一个测试套件,测试套件与JUnit相类似,包含了几个测试用例,你可以使用add()方法来把测试用例添加到测试套件中。
我们来使用YUITest重测一下清单5中的源代码。
清单12说明了如何为该测试创建一个套件和一个测试用例。
清单12.测试套件和测试用例
114YUI().use("test","console",function(Y){
115
116varsuite=newY.Test.Suite("Temperatureconversionsuite");
117
118//addatestcase
119suite.add(newY.Test.Case({
120name:
"Temperatureconversion?
121));
122});
清单12生成了一个名为Temperatureconversionsuite的套件,以及一个名为Temperatureconversion的测试用例。
现在,你可以在对象字面量(objectliteral)内部编写测试方法了,该字面量会被作为参数传递给Y.Test.Case构造函数,如清单13所示。
清单13.填写了测试方法的测试用例
123suite.add(newY.Test.Case({
124name:
"Temperatureconversion",
125
126setUp:
function(){
127this.celsius1=20;
128this.celsius2=30;
129
130this.fahrenheit1=68;
131this.fahrenheit2=86;
132},
133
134testConversionCtoF:
function(){
135Y.Assert.areEqual(this.fahrenheit1,
136convertFromCelsiusToFahrenheit(this.celsius1));
137
138Y.Assert.areEqual(this.fahrenheit2,
139convertFromCelsiusToFahrenheit(this.celsius2));
140},
141
142testConversionFtoC:
function(){
143Y.Assert.areEqual(this.celsius1,
144convertFromFahrenheitToCelsius(this.fahrenheit1));
145
146Y.Assert.areEqual(this.celsius2,
147convertFromFahrenheitToCelsius(this.fahrenheit2));
148}
149}));
你可能已经注意到了在清单13中:
1.setUp()方法是可用的。
YUI在测试用例和测试套件层面都提供了setUp()和tearDown()方法。
2.测试方法的名称以test这一词作为开始,他们包含有断言。
3.该例子使用的是Y.Assert.areEqual()这一断言类型,其类似于QUnit中的equal()函数。
4.YUITest提供了多种多样的断言方法,比如说:
4.1.Y.Assert.areSame(),该断言相当于QUnit中的strictEqual()。
4.2.数据类型断言(Y.Assert.isArray(),Y.Assert.isBoolean(),Y.Assert.isNumber()等)。
4.3.特殊值的断言(Y.Assert.isFalse(),Y.Assert.isNaN(),Y.Assert.isNull()等)。
若要发起YUI中的测试,使用Y.Test.Runner对象。
你需要把套件或是测试用例添加到这一对象中,然后调用run()方法来运行测试。
清单14展示了如何运行清单13中创建的测试。
清单14.运行YUI测试
150Y.Test.Runner.add(suite);
151Y.Test.Runner.run();
默认情况下,结果被输出在浏览器的控制台中(如果你的浏览器支持控制台的话),一种更好的做法是使用Yahoo!
Console组件来输出结果。
若要使用Yahoo!
Console组件,你需要采用Y.Console的构造函数,并把该控制台和HTML运行器的一个DOM元素绑在一起,如清单15所示。
清单15.Yahoo!
Console
152varconsole=newY.Console({
153verbose:
true,
154newestOnTop:
false,
155width:
"600px"
156});
157
158console.render('#testLogger');
清单15说明了如何使用几个参数来配置控制台,该控制台会在一个其id等于testLogger的DOM元素内部进行渲染。
HTML运行器需要更新,添加控制台所引用的DOM元素,如清单16所示。
清单16.HTML运行器更新为支持Yahoo!
Console
159
160
161