如何进行高效JavaScript单元测试
2011-12-13 14:14
465 查看
好久没有贴文了。。今天CSDN上看到一篇博客介绍JsTestDriver 贴下来供大家学习参考之用
以下是原文链接地址:http://sd.csdn.net/a/20111201/308376.html
导读:能在一个浏览器上运行的JavaScript并不一定能在其他浏览器上运行。如果没有对代码进行单元测试,那么在决定升级或支持新浏览器的时候,组织就需要花钱测试或重新测试Web应用程序。在本文中,了解JavaScript单元测试如何帮助您降低测试成本,轻松支持更多浏览器。
一个损坏的JavaScript代码示例
Web应用程序面临的一个最大挑战是支持不同版本的Web浏览器。能在Safari上运行的JavaScript代码不一定能在Windows® Internet Explorer (IE)、Firefox或Google Chrome上运行。这个挑战的根源是呈现层中的JavaScript代码从一开始就没有进行测试。如果没有对代码进行单元测试,那么在升级或支持新浏览器后,组织可能需要花钱反复测试Web应用程序。本文将展示如何通过高效的JavaScript代码单元测试降低测试成本。
一个常见用例是登录表单JavaScript验证。考虑清单1中的表单。
<FORM>
<table>
<tr>
<td>Username</td>
<td><input type="text" id="username"/></td>
<td><span id="usernameMessage"></span></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" id="password"/></td>
<td><span id="passwordMessage"></span></td>
</tr>
<tr>
<td><input type="button" onclick="new appnamespace.
ApplicationUtil().validateLoginForm()" value="Submit"/></td>
</tr>
</table>
</FORM>
这个表单很简单,仅包含用户名和密码字段。单击提交按钮时,将通过
清单 2.损坏的ApplicationUtil对象代
appnamespace = {};
appnamespace.ApplicationUtil = function() {};
appnamespace.ApplicationUtil.prototype.validateLoginForm = function(){
var error = true;
document.getElementById("usernameMessage").innerText = "";
document.getElementById("passwordMessage").innerText = "";
if (!document.getElementById("username").value) {
document.getElementById("usernameMessage").innerText =
"This field is required";
error = false;
}
if (!document.getElementById("password").value) {
document.getElementById("passwordMessage").innerText =
"This field is required";
error = false;
}
return error; };
在清单 2中,
上面的代码能够在Internet Explorer 8和Safari 5.1上工作,但无法在 Firefox 3.6 上工作,原因是Firefox不支持
这个问题的一个解决方案是进行自动化单元测试,检查代码是不是跨浏览器兼容。
JsTestDriver
JsTestDriver library是最好的JavaScript单元测试框架之一,它为JavaScript代码提供了跨浏览器测试。图 1展示了JsTestDriver的架构。
图 1.JsTestDriver架构
![](http://articles.csdn.net/uploads/allimg/111201/09330264K-0.gif)
捕获不同的浏览器之后,服务器会负责将JavaScript测试用例运行程序代码加载到浏览器中。可以通过命令行捕获浏览器,也可以通过将浏览器指向服务器URL来捕获浏览器。一旦捕获到浏览器,该浏览器就被称为从属浏览器。服务器可以加载JavaScript代码,在每个浏览器上执行测试用例,然后将结果返回给客户端。
客户端(命令行)需要以下两个主要项目:
JavaScript文件,即源文件和测试文件
配置文件,用于组织源文件和测试文件的加载
这个架构比较灵活,允许单个服务器从网络中的其他机器捕获任意数量的浏览器。例如,如果您的代码在Linux上运行但您想针对另一个Windows机器上的Microsoft Internet Explorer运行您的测试用例,那么这个架构很有用。
要使用JsTestDriver库,请先下载最新版的JsTestDriver 1.3.2。
jsTestDriver是开源项目
jsTestDriver是Apache 2.0 许可下的一个开源项目,托管在Google Code上,后者是一个类似于SourceForge的项目存储库。只要使用Open Source Initiative批准的许可,开发人员就能在这个存储库中创建和管理公共项目。
还有许多其他JavaScript单元测试工具,请参见下面的参考资料部分中的其他工具,比如Dojo Objective Harness (DOH)。
编写单元测试代码
现在开始编写JavaScript测试用例。为简单起见,我将测试以下用例:
用户名和密码字段均为空。
用户名为空,密码不为空。
用户名不为空,密码为空。
清单 3显示了表示TestCase对象的
清单 3.ApplicationUtilTest 对象代码的一部分
ApplicationUtilTest = TestCase("ApplicationUtilTest");
ApplicationUtilTest.prototype.setUp = function () {
/*:DOC += <FORM action=""><table><tr><td>Username</td><td>
<input type="text" id="username"/></td><td><span id="usernameMessage">
</span></td></tr><tr><td>Password</td><td>
<input type="password" id="password"/></td><td><span id="passwordMessage"
></span></td></tr></table></FORM>*/
};
ApplicationUtilTest.prototype.testValidateLoginFormBothEmpty = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
/* Simulate empty user name and password */
document.getElementById("username").value = "";
document.getElementById("password").value = "";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!", "This field is required",
document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!", "This field is required",
document.getElementById("passwordMessage").innerHTML);
};
在
在JsTestDriver中,可以使用以下构件:
其他方法的代码包含其他测试用例。清单 4 显示了测试用例对象的完整代码。
清单 4. ApplicationUtil 对象完整代码
pplicationUtilTest = TestCase("ApplicationUtilTest");
ApplicationUtilTest.prototype.setUp = function () {
/*:DOC += <FORM action=""><table><tr><td>Username</td><td>
<input type="text" id="username"/></td><td><span id="usernameMessage">
</span></td></tr><tr><td>Password</td><td>
<input type="password" id="password"/></td><td><span id="passwordMessage"
></span></td></tr></table></FORM>*/
};
ApplicationUtilTest.prototype.testValidateLoginFormBothEmpty = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
/* Simulate empty user name and password */
document.getElementById("username").value = "";
document.getElementById("password").value = "";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!", "This field is required",
document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!", "This field is required",
document.getElementById("passwordMessage").innerHTML);
};
ApplicationUtilTest.prototype.testValidateLoginFormWithEmptyUserName = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
/* Simulate empty user name and password */
document.getElementById("username").value = "";
document.getElementById("password").value = "anyPassword";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!",
"This field is required", document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!",
"", document.getElementById("passwordMessage").innerHTML);
};
ApplicationUtilTest.prototype.testValidateLoginFormWithEmptyPassword = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
document.getElementById("username").value = "anyUserName";
document.getElementById("password").value = "";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!",
"", document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!",
"This field is required", document.getElementById("passwordMessage").
innerHTML); };
配置用于测试的不同浏览器
测试JavaScript代码的一个推荐实践是将JavaScript源代码和测试代码放置在不同的文件夹中。对于图 2中的示例,我将JavaScript源文件夹命名为“js-src”,将JavaScript测试文件夹命名为“js-test”,它们都位于“js”父文件夹下。
图 2. JavaScript测试文件夹结构
![](http://articles.csdn.net/uploads/allimg/111201/0933021638-1.jpg)
组织好源和测试文件夹后,必须提供配置文件。默认情况下,
清单 5.JsTestDriver配置文件内容
server: http://localhost:9876
load:
- js-src/*.js
- js-test/*.js
配置文件采用YAML格式。
现在,我们将在IE、Firefox和Safari浏览器上运行测试用例类。
要运行测试用例类,需要启动服务器。您可以使用以下命令行启动
启动并捕获浏览器后,可以通过以下命令行运行测试用例类:
清单 6.第一轮结果
修复JavaScript代码并重新运行测试用例
我们来修复损坏的JavaScript代码。我们将使用
清单 7.修复后的ApplicationUtil对象代码
appnamespace = {};
appnamespace.ApplicationUtil = function() {};
appnamespace.ApplicationUtil.prototype.validateLoginForm = function(){
var error = true;
document.getElementById("usernameMessage").innerHTML = "";
document.getElementById("passwordMessage").innerHTML = "";
if (!document.getElementById("username").value) {
document.getElementById("usernameMessage").innerHTML =
"This field is required";
error = false;
}
if (!document.getElementById("password").value) {
document.getElementById("passwordMessage").innerHTML =
"This field is required";
error = false;
}
return error; };
使用
清单 8.第二轮运行结果
结束语
在本文中,您了解了如何使用一个最强大的JavaScript单元测试工具(JsTestDriver)在不同的浏览器上测试JavaScript应用程序代码。还了解了什么是JsTestDriver,如何配置它,以及如何在Web应用程序中使用它来确保应用程序的JavaScript代码的质量和可靠性。
以下是原文链接地址:http://sd.csdn.net/a/20111201/308376.html
导读:能在一个浏览器上运行的JavaScript并不一定能在其他浏览器上运行。如果没有对代码进行单元测试,那么在决定升级或支持新浏览器的时候,组织就需要花钱测试或重新测试Web应用程序。在本文中,了解JavaScript单元测试如何帮助您降低测试成本,轻松支持更多浏览器。
一个损坏的JavaScript代码示例
Web应用程序面临的一个最大挑战是支持不同版本的Web浏览器。能在Safari上运行的JavaScript代码不一定能在Windows® Internet Explorer (IE)、Firefox或Google Chrome上运行。这个挑战的根源是呈现层中的JavaScript代码从一开始就没有进行测试。如果没有对代码进行单元测试,那么在升级或支持新浏览器后,组织可能需要花钱反复测试Web应用程序。本文将展示如何通过高效的JavaScript代码单元测试降低测试成本。
一个常见用例是登录表单JavaScript验证。考虑清单1中的表单。
<FORM>
<table>
<tr>
<td>Username</td>
<td><input type="text" id="username"/></td>
<td><span id="usernameMessage"></span></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" id="password"/></td>
<td><span id="passwordMessage"></span></td>
</tr>
<tr>
<td><input type="button" onclick="new appnamespace.
ApplicationUtil().validateLoginForm()" value="Submit"/></td>
</tr>
</table>
</FORM>
这个表单很简单,仅包含用户名和密码字段。单击提交按钮时,将通过
ApplicationUtil执行一个特定的表单验证。以下是负责验证HTML表单的JavaScript对象。清单2显示了
ApplicationUtil对象的代码。
清单 2.损坏的ApplicationUtil对象代
appnamespace = {};
appnamespace.ApplicationUtil = function() {};
appnamespace.ApplicationUtil.prototype.validateLoginForm = function(){
var error = true;
document.getElementById("usernameMessage").innerText = "";
document.getElementById("passwordMessage").innerText = "";
if (!document.getElementById("username").value) {
document.getElementById("usernameMessage").innerText =
"This field is required";
error = false;
}
if (!document.getElementById("password").value) {
document.getElementById("passwordMessage").innerText =
"This field is required";
error = false;
}
return error; };
在清单 2中,
ApplicationUtil对象提供一个简单验证:用户名和密码字段都已填充。如果某个字段为空,就会显示一条错误消息:
This field is required。
上面的代码能够在Internet Explorer 8和Safari 5.1上工作,但无法在 Firefox 3.6 上工作,原因是Firefox不支持
innerText属性。通常,(上述代码和其他类似JavaScript代码中的)主要问题是不容易发现编写的JavaScript代码是不是跨浏览器兼容的。
这个问题的一个解决方案是进行自动化单元测试,检查代码是不是跨浏览器兼容。
JsTestDriver
JsTestDriver library是最好的JavaScript单元测试框架之一,它为JavaScript代码提供了跨浏览器测试。图 1展示了JsTestDriver的架构。
图 1.JsTestDriver架构
![](http://articles.csdn.net/uploads/allimg/111201/09330264K-0.gif)
捕获不同的浏览器之后,服务器会负责将JavaScript测试用例运行程序代码加载到浏览器中。可以通过命令行捕获浏览器,也可以通过将浏览器指向服务器URL来捕获浏览器。一旦捕获到浏览器,该浏览器就被称为从属浏览器。服务器可以加载JavaScript代码,在每个浏览器上执行测试用例,然后将结果返回给客户端。
客户端(命令行)需要以下两个主要项目:
JavaScript文件,即源文件和测试文件
配置文件,用于组织源文件和测试文件的加载
这个架构比较灵活,允许单个服务器从网络中的其他机器捕获任意数量的浏览器。例如,如果您的代码在Linux上运行但您想针对另一个Windows机器上的Microsoft Internet Explorer运行您的测试用例,那么这个架构很有用。
要使用JsTestDriver库,请先下载最新版的JsTestDriver 1.3.2。
jsTestDriver是开源项目
jsTestDriver是Apache 2.0 许可下的一个开源项目,托管在Google Code上,后者是一个类似于SourceForge的项目存储库。只要使用Open Source Initiative批准的许可,开发人员就能在这个存储库中创建和管理公共项目。
还有许多其他JavaScript单元测试工具,请参见下面的参考资料部分中的其他工具,比如Dojo Objective Harness (DOH)。
编写单元测试代码
现在开始编写JavaScript测试用例。为简单起见,我将测试以下用例:
用户名和密码字段均为空。
用户名为空,密码不为空。
用户名不为空,密码为空。
清单 3显示了表示TestCase对象的
ApplicationUtilTest对象的部分代码。
清单 3.ApplicationUtilTest 对象代码的一部分
ApplicationUtilTest = TestCase("ApplicationUtilTest");
ApplicationUtilTest.prototype.setUp = function () {
/*:DOC += <FORM action=""><table><tr><td>Username</td><td>
<input type="text" id="username"/></td><td><span id="usernameMessage">
</span></td></tr><tr><td>Password</td><td>
<input type="password" id="password"/></td><td><span id="passwordMessage"
></span></td></tr></table></FORM>*/
};
ApplicationUtilTest.prototype.testValidateLoginFormBothEmpty = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
/* Simulate empty user name and password */
document.getElementById("username").value = "";
document.getElementById("password").value = "";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!", "This field is required",
document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!", "This field is required",
document.getElementById("passwordMessage").innerHTML);
};
ApplicationUtilTest对象通过JsTestDriver
TestCase对象创建。如果您熟悉JUnit框架,那么您肯定熟悉
setUp和
testXXX方法。
setUp方法用于初始化测试用例。对于本例,我使用该方法来声明一个HTML片段,该片段将用于其他测试用例方法。
DOC注释是一个JsTestDriver惯用语,可以用于轻松声明一个HTML片段。
在
testValidateLoginFormBothEmpty方法中,创建了一个
ApplicationUtil对象,并在测试用例方法中使用该对象。然后,代码通过检索用户名和密码的DOM元素并将它们的值设置为空值来模拟输入空用户名和密码。可以调用
validateLoginForm方法来执行实际表单验证。最后,将调用
assertEquals来确保
usernameMessage和
passwordMessagespan元素中的消息是正确的,即:
This field is required。
在JsTestDriver中,可以使用以下构件:
fail ("msg"):表明测试一定会失败,消息参数将显示为一条错误消息。
assertTrue ("msg", actual):断定实际参数正确。否则,消息参数将显示为一条错误消息。
assertFalse ("msg", actual):断定实际参数错误。否则,消息参数将显示为一条错误消息。
assertSame ("msg", expected, actual):断定实际参数与预期参数相同。否则,消息参数将显示为一条错误消息。
assertNotSame ("msg", expected, actual):断定实际参数与预期参数不相同。否则,消息参数将显示为一条错误消息。
assertNull ("msg", actual):断定参数为空。否则,消息参数将显示为一条错误消息。
assertNotNull ("msg", actual):断定实际参数不为空。否则,消息参数将显示为一条错误消息。
其他方法的代码包含其他测试用例。清单 4 显示了测试用例对象的完整代码。
清单 4. ApplicationUtil 对象完整代码
pplicationUtilTest = TestCase("ApplicationUtilTest");
ApplicationUtilTest.prototype.setUp = function () {
/*:DOC += <FORM action=""><table><tr><td>Username</td><td>
<input type="text" id="username"/></td><td><span id="usernameMessage">
</span></td></tr><tr><td>Password</td><td>
<input type="password" id="password"/></td><td><span id="passwordMessage"
></span></td></tr></table></FORM>*/
};
ApplicationUtilTest.prototype.testValidateLoginFormBothEmpty = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
/* Simulate empty user name and password */
document.getElementById("username").value = "";
document.getElementById("password").value = "";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!", "This field is required",
document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!", "This field is required",
document.getElementById("passwordMessage").innerHTML);
};
ApplicationUtilTest.prototype.testValidateLoginFormWithEmptyUserName = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
/* Simulate empty user name and password */
document.getElementById("username").value = "";
document.getElementById("password").value = "anyPassword";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!",
"This field is required", document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!",
"", document.getElementById("passwordMessage").innerHTML);
};
ApplicationUtilTest.prototype.testValidateLoginFormWithEmptyPassword = function () {
var applicationUtil = new appnamespace.ApplicationUtil();
document.getElementById("username").value = "anyUserName";
document.getElementById("password").value = "";
applicationUtil.validateLoginForm();
assertEquals("Username is not validated correctly!",
"", document.getElementById("usernameMessage").innerHTML);
assertEquals("Password is not validated correctly!",
"This field is required", document.getElementById("passwordMessage").
innerHTML); };
配置用于测试的不同浏览器
测试JavaScript代码的一个推荐实践是将JavaScript源代码和测试代码放置在不同的文件夹中。对于图 2中的示例,我将JavaScript源文件夹命名为“js-src”,将JavaScript测试文件夹命名为“js-test”,它们都位于“js”父文件夹下。
图 2. JavaScript测试文件夹结构
![](http://articles.csdn.net/uploads/allimg/111201/0933021638-1.jpg)
组织好源和测试文件夹后,必须提供配置文件。默认情况下,
JsTestDriver运行程序会寻找名为jsTestDriver.conf的配置文件。您可以从命令行更改配置文件名称。清单 5显示了
JsTestDriver配置文件的内容。
清单 5.JsTestDriver配置文件内容
server: http://localhost:9876
load:
- js-src/*.js
- js-test/*.js
配置文件采用YAML格式。
server指令指定测试服务器的地址,
load指令指出了将哪些JavaScript文件加载到浏览器中以及加载它们的顺序。
现在,我们将在IE、Firefox和Safari浏览器上运行测试用例类。
要运行测试用例类,需要启动服务器。您可以使用以下命令行启动
JsTestDriver服务器:
java -jar JsTestDriver-1.3.2.jar --port 9876 --browser "[Firefox Path]", "[IE Path]","[Safari Path]"使用这个命令行,服务器将以Port 9876启动,捕获您的机器上的Firefox、IE和Safari浏览器。
启动并捕获浏览器后,可以通过以下命令行运行测试用例类:
java -jar JsTestDriver-1.3.2.jar --tests all运行命令后,您将看到第一轮结果,如清单 6 所示。
清单 6.第一轮结果
Total 9 tests (Passed: 6; Fails: 3; Errors: 0) (16.00 ms) Firefox 3.6.18 Windows: Run 3 tests (Passed: 0; Fails: 3; Errors 0) (8.00 ms) ApplicationUtilTest.testValidateLoginFormBothEmpty failed (3.00 ms): AssertError: Username is not validated correctly! expected "This field is required" but was "" Error("Username is not validated correctly! expected \"This field is required\" but was \"\"")@:0()@http://localhost :9876/test/js-test/TestApplicationUtil.js:16 ApplicationUtilTest.testValidateLoginFormWithEmptyUserName failed (3.00 ms): AssertError: Username is not validated correctly! expected "This field is required" but was "" Error("Username is not validated correctly! expected \"This field is required\" but was \"\"")@:0()@http://localhost:9876/test /js-test/TestApplicationUtil.js:29 ApplicationUtilTest.testValidateLoginFormWithEmptyPassword failed (2.00 ms): AssertError: Password is not validated correctly! expected "This field is required" but was "" Error("Password is not validated correctly! expected \"This field is required\" but was \"\"")@:0()@http://localhost:9876/test/ js-test/TestApplicationUtil.js:42 Safari 534.50 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (2.00 ms) Microsoft Internet Explorer 8.0 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (16.00 ms) Tests failed: Tests failed. See log for details.注意,在清单 6 中,主要问题出在 Firefox 上。测试在 Internet Explorer 和 Safari 上均可顺利运行。
修复JavaScript代码并重新运行测试用例
我们来修复损坏的JavaScript代码。我们将使用
innerHTML替代
innerText。清单 7显示了修复后的
ApplicationUtil对象代码。
清单 7.修复后的ApplicationUtil对象代码
appnamespace = {};
appnamespace.ApplicationUtil = function() {};
appnamespace.ApplicationUtil.prototype.validateLoginForm = function(){
var error = true;
document.getElementById("usernameMessage").innerHTML = "";
document.getElementById("passwordMessage").innerHTML = "";
if (!document.getElementById("username").value) {
document.getElementById("usernameMessage").innerHTML =
"This field is required";
error = false;
}
if (!document.getElementById("password").value) {
document.getElementById("passwordMessage").innerHTML =
"This field is required";
error = false;
}
return error; };
使用
--test all命令行参数重新运行测试用例对象。清单 8 显示了第二轮运行结果。
清单 8.第二轮运行结果
Total 9 tests (Passed: 9; Fails: 0; Errors: 0) (9.00 ms) Firefox 3.6.18 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (9.00 ms) Safari 534.50 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (5.00 ms) Microsoft Internet Explorer 8.0 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (0.00 ms)如清单 8所示,JavaScript代码现在在IE、Firefox和Safari上都能正常运行。
结束语
在本文中,您了解了如何使用一个最强大的JavaScript单元测试工具(JsTestDriver)在不同的浏览器上测试JavaScript应用程序代码。还了解了什么是JsTestDriver,如何配置它,以及如何在Web应用程序中使用它来确保应用程序的JavaScript代码的质量和可靠性。
相关文章推荐
- 如何进行高效JavaScript单元测试
- 如何进行高效JavaScript单元测试
- 如何进行高效的Rails单元测试
- 如何进行高效的Rails单元测试
- VS2005如何进行单元测试
- VS2005如何进行单元测试
- VS2005下如何进行单元测试(转载)
- 如何进行Android单元测试
- 如何使用JavaScript和正则表达式进行数据验证
- 如何高效学习JavaScript? JavaScript学习方法!
- SEO是什么,如何进行才高效!
- vs.2008中如何对抽象类私有方法进行单元测试
- Nunit中如何进行事务性单元测试
- 如何进行单元测试
- 对 JavaScript 进行单元测试的工具
- 如何进行单元测试(转贴)
- XCode 内置了 OCUnit 单元测试框架,但目前最好用的测试框架应该是 GHUnit。通过 GHUnit + OCMock 组合,我们可以在 iOS 下进行较强大的单元测试功能。本文将演示如何在
- 如何在eclipse中通过Juit进行单元测试
- 如何进行JavaScript的BOM编程?