最近在項目中經常使用jQuery做網站前端開發,功能開發完成後都是手動測試,想着是否可以學習一下jQuery的單元測試框架,以便後續在寫jQuery的時候做一下單元測試,於是便學習了一個強大的jQuery單元測試框架。
一、簡單使用
Qunit是由jQuery團隊成員開發的一個強大的jQuery單元測試框架,目前已被廣泛使用在各個項目中。爲了使用Qunit,只需要在待測試的html頁面中包含2個Qunit文件即可,分別爲qunit.js和qunit.css文件。其中,qunit.js作爲運行器和測試框架,而qunit.css作爲測試套件的頁面顯示測試結果的樣式。
代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<!-- <meta name="viewport" content="width=device-width"> -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.6.0.css">
<script src="https://code.jquery.com/qunit/qunit-2.6.0.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
<script>
test("hello", function() {
ok(true, "world");
});
</script>
</html>
html頁面中必須在<body>元素中放置一個id=“qunit”的元素。
運行該程序,在瀏覽器中看到的效果如下:
圖1
頭部顯示測試套件的標題,若是綠色顯示調,則表示全部通過,如圖1所示,若至少有一個用例測試失敗,則這個顯示條會顯示紅色,如圖2所示。圖1中從上到下分別顯示的是3個checkbox(在後續章節的調試工具裏會具體介紹),瀏覽器的User-Agent信息以及總的測試信息,包括測試的時長,斷言的總個數、斷言成功的個數以及斷言失敗的個數。
如果測試失敗會是什麼情況呢?
我們對上面的代碼做下修改,將函數ok()裏的第一個參數改成false,如下所示:
ok(false, "world");
再次運行程序,在瀏覽器中看到的效果如下:
圖2
上圖中,給出了斷言失敗的錯誤信息,指出了斷言失敗的具體出錯處。
二、斷言
任何單元測試框架的必要元素就是斷言,QUnit提供了大量的斷言,大致可類如下:
圖3
最基本的斷言
ok()僅只有一個請求的參數,如果返回值爲TRUE,這個斷言就會通過,否則就失敗。此外,還接受一個字符串類型的參數作爲測試結果的顯示。not()則與ok()相反,當參數爲FALSE,這個斷言就會通過。
基本對象比較
相比ok()與notOk(),equal()與notEqual()只能操作基本對象類型,效果等同js比較運算符==和!=,當測試結果爲失敗時,實際值和期望值都會顯示在結果裏,如下圖所示。
QUnit.test( "equal test", function( assert ) {
assert.equal( 0, 0, "Zero, Zero; equal succeeds" );
assert.equal( "", 0, "Empty, Zero; equal succeeds" );
assert.equal( "", "", "Empty, Empty; equal succeeds" );
assert.equal( "three", 3, "Three, 3; equal fails" );
assert.equal( null, false, "null, false; equal fails" );
});
圖4
深度比較
deepEqual()與notDeepEqual(),使用更加準確的比較運算符===,可以操作NaN,正則表達式,數組等類型。
比較對象屬性
porpEqual(),使用更加精確的比較運算符===來比較對象的屬性,不同於deepEqual(),這個斷言可以用來比較擁有不同的構造函數和原型的兩個對象。
回調
QUnit支持的回調斷言包括同步回調和異步回調。
1)同步回調
有時候,我們在測試時,並不能確定回調會在什麼時候能被真正調用。面對這種情況,我們可以使用expect()定義一個我們期望的回調個數,參數爲3,實際上我們只定義了2個有回調的函數,運行程序,結果如圖5所示,
QUnit.test( "a test", function( assert ) {
assert.expect( 3 );
function calc( x, operation ) {
return operation( x );
}
var result = calc( 2, function( x ) {
assert.ok( true, "calc() calls operation function" );
return x * x;
});
assert.equal( result, 4, "2 squared equals 4" );
});
2)異步回調
使用assert.async()定義一個done函數,當操作結束的時候,調用done函數,完成對異步回調的測試。
QUnit.test( "assert.async() test", function( assert ) {
var done = assert.async();
var input = $( "#test-input" ).focus();
setTimeout(function() {
assert.equal( document.activeElement, input[0], "Input was focused" );
done();
});
});
三、分組
QUnit支持將用例進行分組,對測試用例分組後,我們便可以指定跑哪組用例,換個角度來說,也就是我們可以將我們經常用的測試用例進行模塊封裝,提高測試用例利用效率。
QUnit.module( "group a" );
QUnit.test( "a basic test example", function( assert ) {
assert.ok( true, "this test is fine" );
});
QUnit.test( "a basic test example 2", function( assert ) {
assert.ok( true, "this test is fine" );
});
QUnit.module( "group b" );
QUnit.test( "a basic test example 3", function( assert ) {
assert.ok( true, "this test is fine" );
});
QUnit.test( "a basic test example 4", function( assert ) {
assert.ok( true, "this test is fine" );
});
運行該程序,頁面中會多出一個Module的下拉框,可以選中相應的測試用例組,進行測試。
圖6
四、調試工具
Hide passed tests
選中這個checkbox,頁面會隱藏通過的所有測試,當有大量的測試且只有少數測試失敗的情況下,這個選項是挺有用的。此外,當我們選中這個checkbox後,點擊Rerun按鈕再次運行時,頁面重新載入時只會測試上次未通過的測試。
Check for Globals
選中這個checkbox,QUnit會生成一個所有屬性在window對象上的清單,在用例運行之前和之後會去檢查差異。如果屬性被增加或被刪除了,測試就會失敗並顯示出差異。因此,這樣可以幫助我們確保單元測試代碼和項目代碼在測試中不會因爲暴露出來的全局變量而造成衝突。
No try-catch
選中這個checkbox,QUnit會在try-catch語句之外運行回調。若測試時拋出異常,測試就會停止。這樣我們便可以直觀的看到瀏覽器拋出的異常,更方便的追溯錯誤的代碼。