`

JsTestDriver library(JavaScript 单元测试框架)

 
阅读更多
一个损坏的 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 架构
JsTestDriver 架构
jsTestDriver 是开源项目

jsTestDriver 是 Apache 2.0 许可 下的一个开源项目,托管在 Google Code 上,后者是一个类似于 SourceForge 的项目存储库。只要使用 Open Source Initiative 批准的 许可,开发人员就能在这个存储库中创建和管理公共项目。

还有许多其他 JavaScript 单元测试工具,请参见下面的 参考资料 部分中的其他工具,比如 Dojo Objective Harness (DOH)。

捕获不同的浏览器之后,服务器会负责将 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 测试文件夹结构
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 代码的质量和可靠性。
分享到:
评论

相关推荐

    javascript测试.docx

    JSTestDriver是一个基于Java的JavaScript单元测试框架,由Google开发。JSTestDriver提供了一个灵活的测试环境,支持跨浏览器测试、Mock对象等功能。使用JSTestDriver,可以对JavaScript代码进行快速、可靠的测试。 ...

    JavaScript Unit Testing 单元测试 PDF

    全书共190页,涵盖了使用Jasmine、YUITest、QUnit和JsTestDriver等流行的JavaScript单元测试框架的实践指南。通过本书,读者将学会同步和异步测试JavaScript应用程序,利用构建和集成管理工具自动化测试,并生成测试...

    JavaScript单元测试工具安装说明书

    JavaScript单元测试工具JS Test Driver是一种高效且方便的测试框架,它允许开发者在无需打开浏览器的情况下进行JavaScript代码的单元测试,类似于Java的单元测试方式。这一工具显著提升了开发效率,减少了对浏览器...

    jstestdriver-1.3.5.zip

    1. JSTestDriver是一个JavaScript测试框架,专为浏览器环境的单元测试而设计,支持多种测试库。 2. SINDI是一个针对Scala的依赖注入框架,用于提升代码的可测试性和可维护性。 3. 开源项目意味着源代码对公众开放,...

    buster-jstestdriver:在Buster.JS上运行JsTestDriver测试

    Buster.JS是一个强大的JavaScript测试框架,它提供了全面的测试解决方案,包括客户端和服务器端的测试。Buster.JS的核心特性包括异步测试支持、模拟对象、断言库以及测试报告的生成。这个框架旨在帮助开发者编写可...

    对JavaScript进行单元测试的工具

    简介单元测试关注的是验证一个模块或一段代码的执行效果是否和设计或预期一样。有些开发人员认为,编写测试用例浪费时间而宁愿去编写新的模块。然而,在处理大型应用程序时,单元测试实际上会节省时间;它能帮助您...

    JsTestDriver Maven Plugin-开源

    使用 Maven 构建执行 JSTestDriver (Javascript) 测试用例。 如果测试用例失败,则构建失败。 在 burke.webster (http://code.google.com/u/burke.webster) 所写的基础上构建。

    sonar-javascript-integrationtests:用JavaScript项目的集成测试结果(测试数量,成功百分比等)扩展SonarQube

    使用声纳属性“ sonar.javascript.jstestdriver.itReportsPath”指向包含surefire报告的目录。 该插件将扫描以“ ITESTS-”为前缀的报告 将“集成测试结果”小部件添加到您的仪表板(此小部件还显示覆盖率信息,...

    编写可维护的JavaScript(中文)

    《编写可维护的JavaScript》向开发人员阐述了如何在团队开发中编写具备高可维护性的JavaScript代码,书中详细说明了作为团队一分子,应该怎么写JavaScript。本书内容涵盖了编码风格、编程技巧、自动化、测试等几方面...

    编写可维护的javascript(英文)

    自动化测试是本书的另一个重点,作者详细介绍了多种自动化测试框架,包括YUI Test Selenium引擎、Yeti、PhantomJS和JsTestDriver等,并讨论了如何将它们与CI(持续集成)系统整合,如Jenkins等,以实现自动化的代码...

    JavaScript Unit Testing(PACKT,2013)

    Cover the most popular JavaScript Unit Testing Frameworks including Jasmine, YUITest, QUnit, and JsTestDriver. Automate and integrate your JavaScript Unit Testing for ease and efficiency.

    maven-jstestdriver-plugin-0.1.8.jar

    maven-jstestdriver-plugin-0.1.8.jar

    前端开发IDE、JS神器WebStorm5教程------免费下载.pdf

    - **JavaScript单元测试**:支持JsTestDriver插件,用于JavaScript应用程序的单元测试,甚至可以测量代码覆盖率。 - **代码检查与快速修复**:集成JSLint和JSHint,对JavaScript代码进行静态分析,找出并修复错误。...

    Webapp Architecture

    - **QUnit**:简洁易用的JavaScript单元测试框架。 - **Jasmine**:行为驱动开发(BDD)风格的测试框架。 - **FireUnit**:在Firefox中运行Jasmine测试的工具。 - **Crosscheck**:跨浏览器测试工具。 - **...

    jspg:JavaScript隐私卫士

    这个实验项目没有得到维护,实际上从来没有发展到稳定的质量。...java -jar JsTestDriver-1.3.2.jar-浏览器firefox,Chrome浏览器--port = 9876 java -jar JsTestDriver-1.3.2.jar-测试所有--testOutput = results

    linear-js:msgpack-rpc +α用于JavaScript语言

    Java Runtime版本1.6或更高版本用于JsTestDriver,闭包编译器和jsdoc-toolkit 制作方法及使用方法 $ make $ cp src/linear.min.js /path/to/somewhere 制定目标 全部与包装相同笔记linear.js和msgpack.codec.js由...

    java源码剖析-JavaJsSonarDemo:一个演示项目,用Sonar演示对Java和JavaScript源的代码分析

    JavaScript-Project 如何 您需要一个正在运行的声纳服务器 和声纳javascript插件 下载jstestdriver.jar并将其安装到本地Maven存储库 mvn install:install-file -Dfile= -DgroupId=com.google.jstestdriver -...

    js实现json数据行到列的转换的实例代码

    为了测试这个转换函数,作者使用了JsTestDriver,这是一个用于自动化测试JavaScript代码的测试框架。通过编写测试用例来验证转换函数的正确性,确保转换后的数据结构能够按照预期工作,并且在图表工具如Ext图表中...

    jstd-jasmine-archetype:使用JsTestDriver和Jasmine进行项目的Maven原型

    通过mvn archetype:generate生成一个新的JsTestDriver-Jasmine-project(请参见下面的代码段)。 在生成pom.xml调整Maven项目属性browser 生成新项目: mvn archetype:generate -DachetypeCatalog=local -...

Global site tag (gtag.js) - Google Analytics