這個表單很簡單,僅包含用戶名和密碼字段。單擊提交按鈕時,將通過ApplicationUtil執行一個特定的表單驗證。以下是負責驗證HTML表單的JavaScript對象。清單2顯示了ApplicationUtil對象的代碼。
在清單 2中,ApplicationUtil對象提供一個簡單驗證:用戶名和密碼字段都已填充。如果某個字段為空,就會顯示一條錯誤消息:This field is required。
JsTestDriver
JsTestDriver library是最好的JavaScript單元測試框架之一,它為JavaScript代碼提供了跨瀏覽器測試。圖 1展示了JsTestDriver的架構。
圖 1.JsTestDriver架構

捕獲不同的瀏覽器之后,服務器會負責將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 和 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代碼的質量和可靠性。