<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

    如何進(jìn)行高效JavaScript單元測(cè)試

    如何進(jìn)行高效JavaScript單元測(cè)試

     導(dǎo)讀:能在一個(gè)瀏覽器上運(yùn)行的JavaScript并不一定能在其他瀏覽器上運(yùn)行。如果沒(méi)有對(duì)代碼進(jìn)行單元測(cè)試,那么在決定升級(jí)或支持新瀏覽器的時(shí)候,組織就需要花錢(qián)測(cè)試或重新測(cè)試Web應(yīng)用程序。在本文中,了解JavaScript單元測(cè)試如何幫助您降低測(cè)試成本,輕松支持更多瀏覽器。

      一個(gè)損壞的JavaScript代碼示例

      Web應(yīng)用程序面臨的一個(gè)最大挑戰(zhàn)是支持不同版本的Web瀏覽器。能在Safari上運(yùn)行的JavaScript代碼不一定能在Windows? Internet Explorer (IE)、Firefox或Google Chrome上運(yùn)行。這個(gè)挑戰(zhàn)的根源是呈現(xiàn)層中的JavaScript代碼從一開(kāi)始就沒(méi)有進(jìn)行測(cè)試。如果沒(méi)有對(duì)代碼進(jìn)行單元測(cè)試,那么在升級(jí)或支持新瀏覽器后,組織可能需要花錢(qián)反復(fù)測(cè)試Web應(yīng)用程序。本文將展示如何通過(guò)高效的JavaScript代碼單元測(cè)試降低測(cè)試成本。

      一個(gè)常見(jiàn)用例是登錄表單JavaScript驗(yàn)證。考慮清單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>
  •   這個(gè)表單很簡(jiǎn)單,僅包含用戶名和密碼字段。單擊提交按鈕時(shí),將通過(guò)ApplicationUtil執(zhí)行一個(gè)特定的表單驗(yàn)證。以下是負(fù)責(zé)驗(yàn)證HTML表單的JavaScript對(duì)象。清單2顯示了ApplicationUtil對(duì)象的代碼。

      清單 2.損壞的ApplicationUtil對(duì)象代

  • 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對(duì)象提供一個(gè)簡(jiǎn)單驗(yàn)證:用戶名和密碼字段都已填充。如果某個(gè)字段為空,就會(huì)顯示一條錯(cuò)誤消息:This field is required。

      上面的代碼能夠在Internet Explorer 8和Safari 5.1上工作,但無(wú)法在 Firefox 3.6 上工作,原因是Firefox不支持innerText屬性。通常,(上述代碼和其他類(lèi)似JavaScript代碼中的)主要問(wèn)題是不容易發(fā)現(xiàn)編寫(xiě)的JavaScript代碼是不是跨瀏覽器兼容的。

      這個(gè)問(wèn)題的一個(gè)解決方案是進(jìn)行自動(dòng)化單元測(cè)試,檢查代碼是不是跨瀏覽器兼容。

      JsTestDriver

      JsTestDriver library是最好的JavaScript單元測(cè)試框架之一,它為JavaScript代碼提供了跨瀏覽器測(cè)試。圖 1展示了JsTestDriver的架構(gòu)。

      圖 1.JsTestDriver架構(gòu)

      捕獲不同的瀏覽器之后,服務(wù)器會(huì)負(fù)責(zé)將JavaScript測(cè)試用例運(yùn)行程序代碼加載到瀏覽器中??梢酝ㄟ^(guò)命令行捕獲瀏覽器,也可以通過(guò)將瀏覽器指向服務(wù)器URL來(lái)捕獲瀏覽器。一旦捕獲到瀏覽器,該瀏覽器就被稱(chēng)為從屬瀏覽器。服務(wù)器可以加載JavaScript代碼,在每個(gè)瀏覽器上執(zhí)行測(cè)試用例,然后將結(jié)果返回給客戶端。

      客戶端(命令行)需要以下兩個(gè)主要項(xiàng)目:

      ● JavaScript文件,即源文件和測(cè)試文件
      ● 配置文件,用于組織源文件和測(cè)試文件的加載

      這個(gè)架構(gòu)比較靈活,允許單個(gè)服務(wù)器從網(wǎng)絡(luò)中的其他機(jī)器捕獲任意數(shù)量的瀏覽器。例如,如果您的代碼在Linux上運(yùn)行但您想針對(duì)另一個(gè)Windows機(jī)器上的Microsoft Internet Explorer運(yùn)行您的測(cè)試用例,那么這個(gè)架構(gòu)很有用。

      要使用JsTestDriver庫(kù),請(qǐng)先下載最新版的JsTestDriver 1.3.2。

      jsTestDriver是開(kāi)源項(xiàng)目

      jsTestDriver是Apache 2.0 許可下的一個(gè)開(kāi)源項(xiàng)目,托管在Google Code上,后者是一個(gè)類(lèi)似于SourceForge的項(xiàng)目存儲(chǔ)庫(kù)。只要使用Open Source Initiative批準(zhǔn)的許可,開(kāi)發(fā)人員就能在這個(gè)存儲(chǔ)庫(kù)中創(chuàng)建和管理公共項(xiàng)目。

      還有許多其他JavaScript單元測(cè)試工具,請(qǐng)參見(jiàn)下面的參考資料部分中的其他工具,比如Dojo Objective Harness (DOH)。

      編寫(xiě)單元測(cè)試代碼

      現(xiàn)在開(kāi)始編寫(xiě)JavaScript測(cè)試用例。為簡(jiǎn)單起見(jiàn),我將測(cè)試以下用例:

      ● 用戶名和密碼字段均為空。
      ● 用戶名為空,密碼不為空。
      ● 用戶名不為空,密碼為空。

      清單 3顯示了表示TestCase對(duì)象的ApplicationUtilTest對(duì)象的部分代碼。

      清單 3.ApplicationUtilTest 對(duì)象代碼的一部分

  • 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對(duì)象通過(guò)JsTestDriver TestCase對(duì)象創(chuàng)建。如果您熟悉JUnit框架,那么您肯定熟悉setUp和testXXX方法。setUp方法用于初始化測(cè)試用例。對(duì)于本例,我使用該方法來(lái)聲明一個(gè)HTML片段,該片段將用于其他測(cè)試用例方法。

      DOC注釋是一個(gè)JsTestDriver慣用語(yǔ),可以用于輕松聲明一個(gè)HTML片段。

      在testValidateLoginFormBothEmpty方法中,創(chuàng)建了一個(gè)ApplicationUtil對(duì)象,并在測(cè)試用例方法中使用該對(duì)象。然后,代碼通過(guò)檢索用戶名和密碼的DOM元素并將它們的值設(shè)置為空值來(lái)模擬輸入空用戶名和密碼??梢哉{(diào)用validateLoginForm方法來(lái)執(zhí)行實(shí)際表單驗(yàn)證。最后,將調(diào)用assertEquals來(lái)確保usernameMessage 和 passwordMessage span元素中的消息是正確的,即:This field is required。

      在JsTestDriver中,可以使用以下構(gòu)件:

      ● fail ("msg"):表明測(cè)試一定會(huì)失敗,消息參數(shù)將顯示為一條錯(cuò)誤消息。
      ● assertTrue ("msg", actual):斷定實(shí)際參數(shù)正確。否則,消息參數(shù)將顯示為一條錯(cuò)誤消息。
      ● assertFalse ("msg", actual):斷定實(shí)際參數(shù)錯(cuò)誤。否則,消息參數(shù)將顯示為一條錯(cuò)誤消息。
      ● assertSame ("msg", expected, actual):斷定實(shí)際參數(shù)與預(yù)期參數(shù)相同。否則,消息參數(shù)將顯示為一條錯(cuò)誤消息。
      ● assertNotSame ("msg", expected, actual):斷定實(shí)際參數(shù)與預(yù)期參數(shù)不相同。否則,消息參數(shù)將顯示為一條錯(cuò)誤消息。
      ● assertNull ("msg", actual):斷定參數(shù)為空。否則,消息參數(shù)將顯示為一條錯(cuò)誤消息。
      ● assertNotNull ("msg", actual):斷定實(shí)際參數(shù)不為空。否則,消息參數(shù)將顯示為一條錯(cuò)誤消息。

      其他方法的代碼包含其他測(cè)試用例。清單 4 顯示了測(cè)試用例對(duì)象的完整代碼。

      清單 4. ApplicationUtil 對(duì)象完整代碼

  • 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);   
  • };

  •  配置用于測(cè)試的不同瀏覽器

      測(cè)試JavaScript代碼的一個(gè)推薦實(shí)踐是將JavaScript源代碼和測(cè)試代碼放置在不同的文件夾中。對(duì)于圖 2中的示例,我將JavaScript源文件夾命名為“js-src”,將JavaScript測(cè)試文件夾命名為“js-test”,它們都位于“js”父文件夾下。

      圖 2. JavaScript測(cè)試文件夾結(jié)構(gòu)

      組織好源和測(cè)試文件夾后,必須提供配置文件。默認(rèn)情況下,JsTestDriver運(yùn)行程序會(huì)尋找名為jsTestDriver.conf的配置文件。您可以從命令行更改配置文件名稱(chēng)。清單 5顯示了JsTestDriver配置文件的內(nèi)容。

      清單 5.JsTestDriver配置文件內(nèi)容

  • server: http://localhost:9876  
  •  
  • load:  
  •   - js-src/*.js  
  •   - js-test/*.js
  •   配置文件采用YAML格式。server指令指定測(cè)試服務(wù)器的地址,load指令指出了將哪些JavaScript文件加載到瀏覽器中以及加載它們的順序。

      現(xiàn)在,我們將在IE、Firefox和Safari瀏覽器上運(yùn)行測(cè)試用例類(lèi)。

      要運(yùn)行測(cè)試用例類(lèi),需要啟動(dòng)服務(wù)器。您可以使用以下命令行啟動(dòng)JsTestDriver服務(wù)器:

  • java -jar JsTestDriver-1.3.2.jar --port 9876 --browser "[Firefox Path]",  
  •           "[IE Path]","[Safari Path]"
  •   使用這個(gè)命令行,服務(wù)器將以Port 9876啟動(dòng),捕獲您的機(jī)器上的Firefox、IE和Safari瀏覽器。

      啟動(dòng)并捕獲瀏覽器后,可以通過(guò)以下命令行運(yùn)行測(cè)試用例類(lèi):

    java -jar JsTestDriver-1.3.2.jar --tests all

     運(yùn)行命令后,您將看到第一輪結(jié)果,如清單 6 所示。

      清單 6.第一輪結(jié)果

  • 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 中,主要問(wèn)題出在 Firefox 上。測(cè)試在 Internet Explorer 和 Safari 上均可順利運(yùn)行。

      修復(fù)JavaScript代碼并重新運(yùn)行測(cè)試用例

      我們來(lái)修復(fù)損壞的JavaScript代碼。我們將使用innerHTML替代innerText。清單 7顯示了修復(fù)后的ApplicationUtil對(duì)象代碼。

      清單 7.修復(fù)后的ApplicationUtil對(duì)象代碼

  • 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 命令行參數(shù)重新運(yùn)行測(cè)試用例對(duì)象。清單 8 顯示了第二輪運(yùn)行結(jié)果。

      清單 8.第二輪運(yùn)行結(jié)果

  • 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代碼現(xiàn)在在IE、Firefox和Safari上都能正常運(yùn)行。

      結(jié)束語(yǔ)

      在本文中,您了解了如何使用一個(gè)最強(qiáng)大的JavaScript單元測(cè)試工具(JsTestDriver)在不同的瀏覽器上測(cè)試JavaScript應(yīng)用程序代碼。還了解了什么是JsTestDriver,如何配置它,以及如何在Web應(yīng)用程序中使用它來(lái)確保應(yīng)用程序的JavaScript代碼的質(zhì)量和可靠性。

    posted on 2011-12-08 14:47 順其自然EVO 閱讀(207) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    <2011年12月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類(lèi)

    隨筆檔案

    文章分類(lèi)

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲AV中文无码乱人伦下载| 亚洲sss综合天堂久久久| 国产91在线|亚洲| 美女被羞羞网站免费下载| 最近2019中文免费字幕在线观看| 免费观看AV片在线播放| 亚洲美女在线国产| 亚洲女人18毛片水真多| 特级毛片爽www免费版| 2021精品国产品免费观看| 亚洲第一网站男人都懂| 亚洲中文字幕久久精品无码2021| 一个人晚上在线观看的免费视频| 久久久久久久91精品免费观看| 国产亚洲自拍一区| 亚洲一区二区三区写真| 免费观看久久精彩视频| 国产成人免费ā片在线观看| 亚洲最大的成网4438| 男人j进女人p免费视频| 99在线精品免费视频九九视| 久久久久亚洲精品天堂久久久久久| 亚洲ts人妖网站| 无码一区二区三区免费| 亚洲国产成人精品女人久久久| 亚洲va乱码一区二区三区| 久久青草91免费观看| 亚洲福利精品一区二区三区| 亚洲AV无码专区在线亚| 免费人成网站在线观看不卡| 无码国产亚洲日韩国精品视频一区二区三区 | 亚洲专区在线视频| 国产精品美女久久久免费 | 亚洲视频在线观看免费视频| jizz在线免费观看| 女人18特级一级毛片免费视频| 亚洲AV无码乱码在线观看富二代 | 精品亚洲福利一区二区| 久久久久久国产a免费观看黄色大片 | 日亚毛片免费乱码不卡一区| 妞干网免费观看视频|