一个损坏的 JavaScript 代码示例
Web 应用程序面临的一个最大挑战是支持不同版本的 Web 浏览器。能在 Safari 上运行的 JavaScript 代码不一定能在 Windows® Internet Explorer (IE)、Firefox 或 Google Chrome 上运行。这个挑战的根源是呈现层中的 JavaScript 代码从一开始就没有进行测试。如果没有对代码进行单元测试,那么在升级或支持新浏览器后,组织可能需要花钱反复测试 Web 应用程序。本文将展示如何通过高效的 JavaScript 代码单元测试降低测试成本。
一个常见用例是登录表单 JavaScript 验证。考虑 清单 1
中的表单。
清单 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 架构
捕获不同的浏览器之后,服务器会负责将 JavaScript 测试用例运行程序代码加载到浏览器中。可以通过命令行捕获浏览器,也可以通过将浏览器指向服务器 URL 来捕获浏览器。一旦捕获到浏览器,该浏览器就被称为从属浏览器。服务器可以加载 JavaScript 代码,在每个浏览器上执行测试用例,然后将结果返回给客户端。
客户端(命令行)需要以下两个主要项目:
- JavaScript 文件,即源文件和测试文件
- 配置文件,用于组织源文件和测试文件的加载
这个架构比较灵活,允许单个服务器从网络中的其他机器捕获任意数量的浏览器。例如,如果您的代码在 Linux 上运行但您想针对另一个 Windows 机器上的 Microsoft Internet Explorer 运行您的测试用例,那么这个架构很有用。
要使用 JsTestDriver 库,请先下载最新版的 JsTestDriver 1.3.2
。
编写单元测试代码
现在开始编写 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
和 passwordMessage
span 元素中的消息是正确的,即: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 对象完整代码
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.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 测试文件夹结构
组织好源和测试文件夹后,必须提供配置文件。默认情况下,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 代码的质量和可靠性。
下载
描述
名字
大小
下载方法
源代码 |
simple.zip |
3.35MB |
HTTP
|
关于下载方法的信息
本文转载于developerWorks,原文在这里
分享到:
相关推荐
JavaScript单元测试是软件开发过程中的一个关键环节,它允许开发者对代码的各个独立部分进行验证,确保它们在预期情况下能够正确工作。JSUnit是专为JavaScript设计的一个单元测试框架,它使得JavaScript应用程序的...
JavaScript单元测试工具JS Test Driver是一种高效且方便的测试框架,它允许开发者在无需打开浏览器的情况下进行JavaScript代码的单元测试,类似于Java的单元测试方式。这一工具显著提升了开发效率,减少了对浏览器...
**多浏览器的JavaScript单元测试工具概述** 在软件开发过程中,单元测试是确保代码质量的关键步骤。对于JavaScript,由于其在不同浏览器中可能存在兼容性问题,因此进行多浏览器的单元测试显得尤为重要。本文将探讨...
JavaScript单元测试是软件开发过程中的重要环节,它用于验证代码的各个独立部分(即单元)是否按预期工作。Jasmine是一款流行的JavaScript测试框架,尤其适用于前端开发者,它提供了丰富的断言库和易于理解的语法,...
总的来说,Testem通过其强大的功能和用户友好的特性,使得JavaScript单元测试变得更加高效和愉快,是现代前端开发不可或缺的工具之一。无论你是个人开发者还是团队协作,Testem都能帮助你确保代码质量,提升开发效率...
JavaScript对象封装与单元测试 JavaScript对象封装是指将JavaScript代码组织成一个对象的形式,以便于测试和维护。单元测试是软件测试的一种,目标是确保每个单元的正确性。在JavaScript开发中,单元测试是非常...
在前端开发领域,尤其是在使用Vue.js这样的现代JavaScript框架进行开发时,进行有效的单元测试显得尤为重要。 #### 二、Vue单元测试的意义 1. **提高代码质量**:通过编写测试用例,可以确保代码逻辑正确无误,...
在JavaScript的世界里,有许多优秀的测试框架和库可供选择,其中JSUnit是一个早期的JavaScript单元测试框架。 **JSUnit简介** JSUnit是由Draney在2002年创建的,它是JavaScript的早期测试框架之一,主要用于Web应用...
QUnit 是一个专门用于 JavaScript 代码的单元测试框架,由 jQuery 团队成员创建,同时也是 jQuery 的官方测试工具。虽然最初与 jQuery 相关,但 QUnit 可以应用于任何普通的 JavaScript 代码,甚至支持在服务器端 ...
【JavaScript 单元测试技术详解】 单元测试是软件开发中不可或缺的一个环节,它专注于验证代码的各个独立组件是否...在实践中,单元测试应成为每个开发者日常工作中不可或缺的一部分,以实现高效、可靠的软件开发。
高效的JavaScript代码单元测试方法!一个损坏的JavaScript代码示例Web应用程序面临的一个最大挑战是支持不同版本的Web浏览器。能在Safari上运行的JavaScript代码不一定能在WindowsInternetExplorer(IE)、Firefox或...
Luna是一个专为JavaScript设计的轻量级且现代化的单元测试框架,它提供了在浏览器环境和Node.js环境中进行测试的强大功能。这个框架的诞生旨在简化测试流程,使得开发者能够更加专注于代码质量,而不再被复杂的测试...
这些框架提供了丰富的断言库和方便的测试组织结构,使得编写和运行单元测试变得简单高效。 在学习和实践单元测试时,应注意以下几点: 1. 测试覆盖:确保测试覆盖了所有可能的输入情况,包括正常路径、边界条件和...
单元测试和功能测试是软件开发中两种关键的自动化测试方法,尤其在面向对象编程和Web应用开发中起着至关重要的作用。它们有助于确保代码质量,减少错误,提高开发效率。 **单元测试**主要关注代码的单一组件或模块...
在IT行业中,软件测试是确保产品质量的关键步骤,而单元测试是软件测试的一种基本类型。本教程将深入探讨如何使用Node.js进行单元测试的实践。Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它以其非阻塞I/O...
单元测试是对软件中的最小可测试单元,通常是函数、方法或类,进行独立验证的过程。它的目标是确保每个单元都能按照预期工作,以便在集成过程中减少错误和问题。而静态测试则是在不执行代码的情况下,通过分析代码...
** Jasmine-Node:JavaScript 单元测试框架** Jasmine-Node 是一个用于 JavaScript 的单元测试框架,它将流行的 Jasmine 测试库扩展到了 Node.js 环境中。Jasmine 是一个行为驱动开发(BDD)的测试框架,它以其...