5

背景:

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

我们计划在我们现有的(遗留)代码和未来的工作中引入 JavaScript 单元测试。我们主要是一家java商店(Spring、Weblogic等)。

我们正在寻找能够与 IDE(IntelliJ 理念)和声纳良好集成的选项,以及能够将它们作为持续集成的一部分运行。

JsTestDriver 似乎勾选了所有方框。

问题:

我们现有的许多 javascript 代码 a) 嵌入到 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();

}
);

In the latter case, my approach would be that the function in question is way too large and should be broken to smaller (units) so that it can be tested. But all the interaction points with DOM, jQuery, datatables, ajax etc makes it really complicated to refactor things in the way we do in Java world to make it more testable.

So, any suggestions for the above to sample cases would be greatly appreciated!

4

2 回答 2

6

To test the following code:

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

You could use the following code:

// 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 );

As you see, it's just the classical setup > run > assert pattern.

于 2012-06-18T13:23:43.347 回答
4

maybe Selenium/SeleniumGrid is usefull for you: http://seleniumhq.org/

It is not a "UnitTest" per definition, but you can write selenium tests with java or python (and many more...) as unit tests. Seleniumtests starts web tests in real browsers, and is quiet good for testing frontends (and dom manipulations).

Edit: today i stumbled upon this site describing different ways for unit-testing especially in a jQuery background: http://addyosmani.com/blog/jquery-testing-tools/

于 2012-06-18T13:17:48.953 回答