2012-06-18 113 views
5

背景:如何單元測試與DOM元素交互的Javascript代碼

我來自Java背景,所以不太熟悉Javascript。

我們正在計劃推出JavaScript的單元測試,以我們現有的(傳統)代碼和未來的工作都。我們主要是Java商店(Spring,Weblogic等)。

我們正在研究,讓我們與IDE(IntelliJ IDEA的)和聲納良好的集成方案,以及能夠運行它們作爲持續集成的一部分。

JsTestDriver似乎勾出所有的箱子。

問:

很多我們現有的JavaScript代碼是內嵌內的JSP)和b)利用jQuery來直接與頁面元素進行交互。

我們應該如何去測試一個函數,在DOM嚴重依賴。下面是我說的某些功能的代碼示例:

function enableOccupationDetailsText(){ 
    $("#fldOccupation").val("Unknown"); 
    $("#fldOccupation_Details").attr("disabled", ""); 
    $("#fldOccupation_Details").val(""); 
    $("#fldOccupation_Details").focus(); 
} 

jQuery(document).ready(function(){ 

    var oTable = $('#policies').dataTable({ 
      "sDom" : 'frplitip', 
       "bProcessing": true, 
       "bServerSide": true, 
       "sAjaxSource": "xxxx.do", 
       "sPaginationType": "full_numbers", 
       "aaSorting": [[ 1, "asc" ]], 
       "oLanguage": { 
        "sProcessing": "Processing...", 
        "sLengthMenu": "Show _MENU_ policies", 
        "sZeroRecords": "No matching policies found", 
        "sInfo":   "Showing _START_ to _END_ of _TOTAL_ policies", 
        "sInfoEmpty": "Showing 0 to 0 of 0 policies", 
        "sInfoFiltered": "(filtered from _MAX_ total policies)", 
        "sInfoPostFix": "", 
        "sSearch":  "Search:", 
        "sUrl":   "", 
        "oPaginate": { 
         "sFirst": "First", 
         "sPrevious": "Previous", 
         "sNext":  "Next", 
         "sLast":  "Last" 
       } 
      }, 
       "fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) { 
         $('td:eq(0)', nRow).html("<a href='/ole/policy/general_details.do?policy_id="+aData[0]+"'>"+aData[0]+"</a>"); 
         return nRow; 

       }, 

       "fnServerData" : function (url, data, callback, settings) { 

       settings.jqXHR = $.ajax({ 
        "url": url, 
        "data": data, 
        "success": function (json) { 
         if (json.errorMessage != null) { 
          var an = settings.aanFeatures.r; 
          an[0].style.fontSize="18px"; 
          an[0].style.backgroundColor="red"; 
          an[0].style.height="70px"; 
          an[0].innerHTML=json.errorMessage; 
          setTimeout('window.location="/xxxx"',1000); 
          //window.location="/xxxxx"; 
         } else { 
          $(settings.oInstance).trigger('xhr', settings); 
          callback(json); 
         } 
        }, 
        "dataType": "json", 
        "cache": false, 
        "error": function (xhr, error, thrown) { 
         if (error == "parsererror") { 
          alert("Unexpected error, please contact system administrator. Press OK to be redirected to home page."); 
          window.location="/xxxx"; 
         } 
        } 
       }); 
       } 

      }); 
     $("#policies_filter :text").attr('id', 'fldKeywordSearch'); 
     $("#policies_length :input").attr('id', 'fldNumberOfRows'); 
     $("body").find("span > span").css("border","3px solid red"); 
     oTable.fnSetFilteringDelay(500); 
     oTable.fnSearchHighlighting(); 
     $("#fldKeywordSearch").focus(); 

} 
); 

在後一種情況下,我的做法是有問題的功能是遠遠過大,應該被打破到更小(單位),以便它可以被測試。但是,所有與DOM,jQuery,數據表,ajax等的交互點都使我們以Java世界中的方式重構事情變得非常複雜,使它更容易被測試。

所以,對於上述樣品的情況下任何建議,將不勝感激!

+2

另請參見[在茉莉花測試中測試DOM操作](http://stackoverflow.com/questions/7672389/testing-dom-manipulating-in-jasmine-test) –

+0

還檢查出phantomjs headless webkit – obimod

回答

6

要測試下面的代碼:

function enableOccupationDetailsText(){ 
    $("#fldOccupation").val("Unknown"); 
    $("#fldOccupation_Details").attr("disabled", ""); 
    $("#fldOccupation_Details").val(""); 
    $("#fldOccupation_Details").focus(); 
} 

您可以使用下面的代碼:

// First, create the elements 
$('<input>', { id: 'fldOccupation' }).appendTo(document.body); 
$('<input>', { disabled: true, id: 'fldOccupation_Details' }) 
    .appendTo(document.body); 

// Then, run the function to test 
enableOccupationDetailsText(); 

// And test 
assert($('#fldOccupation').val(), 'Unknown'); 
assert($('#fldOccupation_Details').prop('disabled'), false); 

正如你看到的,它只是古典setup > run > assert圖案。

+0

什麼是撕下來那些DOM對象,以便您沒有一個測試會干擾另一個測試?這是好的做法嗎?如果是這樣,怎麼樣? –

+2

@GregWoods,你可以用'$('#fldOccupation')。remove(); $('#fldOccupation_Details')。remove();'或簡單的'$(document.body.children).remove();' –

4

也許硒/ SeleniumGrid是有用的你:http://seleniumhq.org/

它不是一個「單元測試」根據定義,但你可以寫Selenium測試與Java或Python(以及更多......)作爲單元測試。 Seleniumtests在真正的瀏覽器中開始Web測試,對測試前端(和dom操作)非常安靜。

編輯:今天我偶然發現了這個網站描述特別是在jQuery的背景單元測試不同的方式:http://addyosmani.com/blog/jquery-testing-tools/