QUnit入門 (一)


  作者Aurelio De Rosa jQuery in Action(一定翻了幾遍了吧) 第三版 和 Instant jQuery Selectors 的作者,並且是擁有着超過五年的HTML, CSS, Sass, JavaScript 和 PHP的開發經驗的全棧(full-stack)和webapp開發工程師。不但精通JavaScript和 HTML5 APIs,而且也在web安全、可訪問性、性能和方面有着深刻的造詣。(sitepoint:http://www.sitepoint.com/author/aderosa/)

  軟件測試是給定一組輸入值,比較真實值和期待值之間異同的過程。軟件測試,特別是單元測試對於軟件開發人員是必不可少的。不幸運的是,許多開發人員非常懼怕單元測試。

  JS里面有許多可以供我們選擇進行單元測試的框架。比如,Mocha, Selenium, jasmine 和 QUnit。本文將重點講述Qunit,Qunit 由開發了許多大名鼎鼎的js庫,包括了的jQuery 、jQuery UI等的Jquery團隊(jQuery team)開發。

  1、配置QUnit。

  QUnit本身非常低簡單,並且非常方便去使用。主要的概念可以花費幾個小時內掌握。

  首先安裝QUnit,有三種方式:

    官網下載源文件; 引用CDN; 使用 bower 安裝( bower install --save-dev qunit );  使用npm安裝( npm install --save-dev qunitjs ) ;

    除非開發的項目非常簡單或者項目准備發布到生產環境,否則不建議使用cdn的方式。在本文中我們使用第一種引入QUnit。在QUnit官網下載最新版的 qunit-1.20.0.js 和 qunit-1.20.0.css。創建一個html文件,內容如下:

 1 <!DOCTYPE html>
 2 <html>
 3    <head>
 4       <meta charset="utf-8">
 5       <title>QUnit Example</title>
 6       <link rel="stylesheet" href="../js/qunit/qunit-1.20.0.css">
 7    </head>
 8    <body>
 9       <div id="qunit"></div>
10       <div id="qunit-fixture"></div>
11       <script src="../js/qunit/qunit-1.20.0.js"></script>
12    </body>
13 </html>

   在body里面有兩組div標簽,div#qunit是QUnit用來顯示測試結果的容器。div#qunit-fixture是QUnit留給開發者自己使用的,這個容器允許開發者測試添加,修改或者移除的dom代碼,使開發者不必再為在每個test后為清理dom樹而擔憂。如果將在代碼執行過程中創建html防止在這個div內,QUnit將幫助我們重置掉這些代碼,恢復到初始狀態。

   下面來看如何編寫使用QUnit進行測試。

  2、使用QUnit創建一個測試(test)。

  QUnit創建test有兩個方法:QUnit.test()和QUnit.asyncTest()。正如它們的命名,QUnit.test()常常用來測試同步運行的代碼,QUnit.asyncTest()常常測試異步運行的代碼。在這一小節,主要講解如何使用QUnit.test()測試同步運行的代碼。

  QUnit.test(name, testFunction)

   第一個參數name是用來標記test名稱的字符串。第二個參數,testFunction是一個函數,包含了一個asset作為它的參數。asset包含了許多可供我們斷言的方法。建立一個test。

QUnit.test('My first test', function(assert) {
     // Assertions here... 
});

  上面的代碼段創建了一個名稱為"My first test"的test和沒有包含任何斷言的一個空函數。下面我們來了解

  3、assert斷言方法

  斷言(Assertions)能夠校驗我們的代碼是否如我們期望的那樣運行,是軟件測試的核心。QUnit有許多方法可以校驗。asset作為QUnit.test()的回調函數的第一個參數。

  羅列了asset的主要方法和它們的主要用法:

  deepEqual(value, expected[, message]) : 遞歸性嚴格比較的,針對所有的javascript類型。如果真實值和期待值(expected)屬性,屬性值都一樣並且和有同樣的prototype的話,斷言通過。

   notDeepEqual(value, expected[, message]):與deepEqual()類似,但是用於比較不相等。

  equal(value, expected[, message]) : 真實值和期待值(expected )是否相等,通過非嚴格方式的 "==",可能會轉換類型。

  notEqual(value, expected[, message]) : 與equal()類似,但是用於判斷不想等(轉換類型的不相等)。

  strictEqual(value, expected[, message])真實值和期待值(expected )是否相(===)

  notStrictEqual(value, expected[, message]) : 與strictEqual相反,比較不全等。

  propEqual(value, expected[, message]) : 比較真實和期待(expected的對象的屬性和屬性值是否相同,相同斷言通過。(注意和deepEqual的區別。

  notPropEqual(value, expected[, message]) : 與propEqual相反。

  ok(value[, message]:如果斷言的第一個參數value為true,斷言通過。

 throws(function [, expected ] [, message ]) : 判斷函數是否拋出一個異常,第二個參數可選,代表不一定要檢測拋出異常的類型。

 方法的參數:
 value:等待比較的值,值可以由函數返回或者是對象的一個方法或者一個變量;

 expected : 拿來作對比的值 。在throws()方法中, expected 可以是一個錯誤對象或者錯誤對象的實例、錯誤函數或者構造函數。或者是一個正則表達式 //todo
message : 一個可用來描述斷言的字符串;  
function:要執行的應該返回錯誤的函數;
 

現在:你應該了解了上面的斷言方法和它們參數的含義,下面來看一些代碼實例。
 1 var SEX = [ 'unsigned', 'man', "women" ];
 2 
 3 var Person = function (name, sex) {
 4     this.name = name;
 5     this.sex = sex === undefined || SEX.contains(sex = sex.toLowerCase()) ? sex : SEX[ 0 ];
 6     return this;
 7 };
 8 
 9 Person.prototype.selfIntroduction = function () {
10     console.log('I\'m %s , sex is %s', this.name, this.sex);
11 };
12 
13 var person1 = new Person('Grace', SEX[ 0 ]);
14 var person2 = new Person('Bodhi', 'MAN');
15 var person3 = new Person('Grace', SEX[ 0 ]);
16 
17 QUnit.test("test strictEqual", function (assert) {
18     assert.strictEqual(person1.name, 'Grace', 'strictEqual test pass');
19     assert.notStrictEqual(person1.name, 'Bodhi', 'person2 test pass');
20 });
21 QUnit.test('test array', function (assert) {
22     assert.ok([ 5, 8, 9 ].contains(9), 'test contains pass');
23     assert.notOk([ 5, 8, 9 ].contains(10), 'test not contains pass');
24 });
25 QUnit.test('test equal', function (assert) {
26     assert.strictEqual(person1, person3, 'test person1 and person3 strictEqual pass');
27     assert.propEqual(person1, person3, 'test person1 and person3 propEqual pass.');
28 });
29 QUnit.test('test propEqual', function (assert) {
30     assert.propEqual(person1, {name: 'Grace', sex: 'unsigned'}, 'propEqual pass when prototype is not same.');
31     assert.propEqual(person1, {
32         name: 'Grace',
33         sex: 'man'
34     }, 'propEqual pass when prototype is not same and the value of sex is different.');
35 });
 
        
 1 if (!Array.prototype.indexOf) {
 2     Array.prototype.indexOf = function (elt) {
 3         var len = this.length >>> 0;
 4         var from = Number(arguments[1]) || 0;
 5         from = (from < 0)? Math.ceil(from) : Math.floor(from);
 6         if (from < 0){
 7             from += len;
 8         }
 9         for (; from < len; from++) {
10             if (from in this && this[from] === elt){
11                 return from;
12             }
13         }
14         return -1;
15     };
16 }
17 
18 if (!Array.prototype.contains) {
19     Array.prototype.contains = function (elt) {
20         return (this.length >>> 0) !== 0 && this.indexOf(elt) !== -1;
21     }
22 }

      在上面的例子中,第一個(test strictEqual)使用===進行比較,兩個都通過。assert.ok中如果第一個參數返回true,測試通過。assert.strictEqual比較兩個對象當且僅當兩個對象指向了同一個地址時候才相等,所以第三個測試不通過。

  assert.propEqual會忽略原型僅進行屬性和值的比較。在propEqual的源碼中有這么一段:

 1 function objectValues ( obj ) {
 2     var key, val,
 3         vals = QUnit.is( "array", obj ) ? [] : {};
 4     for ( key in obj ) {
 5         if ( hasOwn.call( obj, key ) ) {
 6             val = obj[ key ];
 7             vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
 8         }
 9     }
10     return vals;
11 }

  在使用propEqual比較時,會根據obj的類型確定一個空的待返回值的類型。遍歷obj中每一個屬於自己的屬性,如果屬性值(value)是一個對象,就以遞歸(前序遍歷)的方式將新的返回的對象中。不會去檢查obj的constructor。

  4、設置Expectations

  當創建一個test時,最好的做法是限制我們希望執行的斷言的數目。在設置了這個后,如果有些斷言沒有被執行,test將會失敗。Qunit使用expect()方法來設置期待斷言的數目。在測試異步的代碼時這種方法非常有用,但是最好是在處理同步的函數時使用它。expect()用法如下:

asset.expect(assertionsNumber);

  assertionsNumber指定了期待斷言的數目。

QUnit.test('max', function(assert) {
   expect(4);
   
   // Assertions here...
});

QUnit.test('isOdd', function(assert) {
   expect(5);
   
   // Assertions here...
});

QUnit.test('sortObj', function(assert) {
   expect(3);
   
   // Assertions here...
});

 5、結論

  主要介紹了如何使用Qunit測試JS代碼。我們看到使用Qunit測試代碼非常地簡單,我們了解了測試同步代碼的方法和在斷言asset的主要方法的使用。最后,我們談到了使用expect()設置斷言數目的重要性並且講述了如何使用這個方法。期待你喜歡這篇文章並且在實際項目中使用它。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM