運用D.O.H進行Javascript應用程序測試(一)

 

D.O.H的文檔不太多,最重要的兩篇(沒有更多的瞭)應該是Unit testing Web 2.0 applications using the Dojo Objective Harness或者Unit Testing Custom Code with the Dojo Objective Harness。本篇先從Unit testing Web 2.0 applications using the Dojo Objective Harness(以下簡稱篇一)的例子入手,再沿著Unit Testing Custom Code with the Dojo Objective Harness的思路解析一下DOH框架的運用。

篇一給出的例子如下

 

被測試代碼:

view plain

  1. dojo.provide("demo.doh.demoFunctions");  
  2.   
  3. //This file contains a collection of helper functions that are not  
  4. //part of any defined dojo class.  
  5.   
  6. demo.doh.demoFunctions.alwaysTrue = function() {  
  7.   //  summary:  
  8.   //    A simple demo helper function that always returns the boolean true when   
  9.   //    called.  
  10.   //  description:  
  11.   //    A simple demo helper function that always returns the boolean true when   
  12.   //    called.  
  13.   return true; // boolean.  
  14. };  
  15.   
  16. demo.doh.demoFunctions.alwaysFalse = function() {  
  17.   //  summary:  
  18.   //    A simple demo helper function that always returns the boolean false when   
  19.   //    called.  
  20.   //  description:  
  21.   //    A simple demo helper function that always returns the boolean false when   
  22.   //    called.  
  23.   return false; // boolean.  
  24. };  
  25.   
  26. demo.doh.demoFunctions.isTrue = function(/* anything */ thing) {  
  27.   //  summary:  
  28.   //    A simple demo helper function that returns true if the thing passed in is  
  29.   //     logically true.  
  30.   //  description:  
  31.   //    A simple demo helper function that returns true if he thing passed in is   
  32.   //    logically true.  
  33.   //    This means that for any defined objects, or Boolean  values of true, it   
  34.   //    should return true,  
  35.   //    For undefined, null, 0, or false, it returns false.  
  36.   //  thing:  
  37.   //    Anything.  Optional argument.  
  38.   var type = typeof thing;  
  39.   if (type === "undefined" || thing === null || thing === 0 || thing === false) {  
  40.     return false; //boolean  
  41.   }  
  42.   return true; // Boolean  
  43. };  
  44.   
  45. demo.doh.demoFunctions.asyncEcho = function(/* function */ callback,  
  46.                                                     /* string */ message){   
  47.   //  summary:  
  48.   //    A simple demo helper function that does an asynchronous echo   
  49. //     of a message.  
  50.   //  description:    
  51.   //    A simple demo helper function that does an asynchronous echo   
  52. //      of a message.  
  53.   //    The callback function is called and passed parameter 'message'   
  54. //       two seconds   
  55.   //    after this helper is called.  
  56.   //  callback:  
  57.   //    The function to call after waiting two seconds.  Takes one  
  58. //       parameter,   
  59.   //    a string message.  
  60.   //  message:  
  61.   //    The message to pass to the callback function.  
  62.   if (dojo.isFunction(callback)) {  
  63.     var handle;  
  64.     var caller = function() {  
  65.       callback(message);  
  66.       clearTimeout(handle);  
  67.       handle = null;  
  68.     };  
  69.     handle = setTimeout(caller, 2000);  
  70.   }  
  71. };  



 

測試代碼是:

 

 

 

 

view plain

dojo.provide("demo.doh.tests.functions.demoFunctions"); 

 

//Import in the code being tested. 

dojo.require("demo.doh.demoFunctions"); 

 

doh.register("demo.doh.tests.functions.demoFunctions", [ 

     function test_alwaysTrue(){ 

          //     summary: 

          //          A simple test of the alwaysTrue function 

          //     description: 

          //          A simple test of the alwaysTrue function 

          doh.assertTrue(demo.doh.demoFunctions.alwaysTrue()); 

     }, 

     function test_alwaysFalse(){ 

          //     summary: 

          //          A simple test of the alwaysFalse function 

          //     description: 

          //          A simple test of the alwaysFalse function 

          doh.assertTrue(!demo.doh.demoFunctions.alwaysFalse()); 

     }, 

     function test_isTrue(){ 

          //     summary: 

          //          A simple test of the isTrue function 

          //     description: 

          //          A simple test of the isTrue function with multiple permutations of  

           //          calling it. 

          doh.assertTrue(demo.doh.demoFunctions.isTrue(true)); 

          doh.assertTrue(!demo.doh.demoFunctions.isTrue(false)); 

          doh.assertTrue(demo.doh.demoFunctions.isTrue({})); 

          doh.assertTrue(!demo.doh.demoFunctions.isTrue()); 

          doh.assertTrue(!demo.doh.demoFunctions.isTrue(null)); 

          doh.assertTrue(!demo.doh.demoFunctions.isTrue(0)); 

     }, 

     { 

          //This is a full test fixture instead of a stand-alone test function.   

          //Therefore, it allows over-riding of the timeout period for a deferred test.   

          //You can also define setup and teardown function 

          //for complex tests, but they are unnecessary here. 

          name: "test_asyncEcho", 

          timeout: 5000, // 5 seconds. 

          runTest: function() { 

               //     summary: 

               //          A simple async test of the asyncEcho function. 

               //     description: 

               //          A simple async test of the asyncEcho function. 

               var deferred = new doh.Deferred(); 

               var message  = "Success"; 

               function callback(string){ 

                    try { 

                         doh.assertEqual(message, string); 

                         deferred.callback(true); 

                    } catch (e) { 

                         deferred.errback(e); 

                    } 

               } 

               demo.doh.demoFunctions.asyncEcho(callback, message); 

               return deferred;      //Return the deferred.  DOH will  

                                     //wait on this object for one of the callbacks to  

                                     //be called, or for the timeout to expire. 

          } 

     } 

]);   

 

上面的測試代碼已經包含瞭DOH框架,我們先運行起來看看結果。同樣,為避免煩瑣的運行環境設置,我們仍然使用firebug來完成全部工作。在跟著教程學習時常遇到的最大問題就是環境問題…如果全部工作都能在firebug中完成的話,那麼顯然是最簡單的瞭–不過仍然還是有一點點環境設置的:

首先,通常我們可以使用Google的CDN發行的dojo,但是遺憾的是,這個發行中並不包含DOH框架,所以,我們需要去dojotoolkit.org下載它的完整發行包,並使用Apache/Nginx等server來host它。這個過程省去不寫,假設最後dojo安裝完成後可以通過http://example.com/dojolib/dojo/dojo.js來訪問。檢查一下這兩個鏈接是否可以訪問:

http://example.com/dojolib/util/doh/runner.js

http://example.com/dojolib/util/doh/_browserRunner.js

其次,你需要參照如何向網頁動態註入dojo這篇文章瞭解如何向網頁動態註入dojo。

假設你已經完成瞭上面的準備。現在,使用Firefox打開任意一個網頁,並啟動Firebug。點擊bookmarklet向該網頁註入dojo。然後在firebug控制臺中輸入以下命令,以註入DOH:

loadModule(“http://example.com/dojolib/util/doh/_browserRunner.js“);

loadModule(“http://example.com/dojolib/util/doh/runner.js“);

略等一會兒,在firebug中輸入ls(doh),如果出現:

image

OK,DOH已經被註入到該網頁當中瞭。這裡有兩個地方要註意:

loadModule和ls通過如何向網頁動態註入dojo一文中提到的方法,向當前窗口註入的兩個函數。其中loadModule的作用是將一個URL所指定的腳本文件註入到當前網頁。而ls===console.dir()函數。

下面,將上文中的被測試代碼和測試代碼輸入到firebug控制臺窗口並運行。此時不會看到任何反饋。再運行下面的命令,完成單元測試:

doh.run();

doh.run()是DOH框架測試的主要入口,也是我們後面自己寫測試頁面需要調用的函數。

 

可是,什麼結果也沒有啊?教程裡象下面這樣的華麗界面呢?

image

顯然,當我們通過firebug運行DOH時,不能期望上面的界面,隻能看到命令行輸出。但是,為什麼命令行輸出也沒有呢?

doh._report()函數用來報告測試結果,但在正常的測試環境下(比如通過util/doh/runner.html運行),它被替換成跟環境相關的函數,而在我們這個測試環境中,仍然使用它原來定義的行為來輸出測試結果。這個函數本身是這樣定義的:

 

 

 

view plaindoh._report = function(){ 

    // summary: 

    //      a private method to be implemented/replaced by the "locally 

    //      appropriate" test runner 

 

    // this.debug("ERROR:"); 

    // this.debug("\tNO REPORTING OUTPUT AVAILABLE."); 

    // this.debug("\tIMPLEMENT doh._report() IN YOUR TEST RUNNER"); 

www.aiwalls.com

    this.debug(this._line); 

    this.debug("| TEST SUMMARY:"); 

    this.debug(this._line); 

    this.debug("\t", this._testCount, "tests in", this._groupCount, "groups"); 

    this.debug("\t", this._errorCount, "errors"); 

    this.debug("\t", this._failureCount, "failures"); 

}   

 

如果你看看debug()函數的定義,你會發現它什麼也不做。因此,我們需要將其替換為console.log:

doh.debug = console.log

現在,再次運行doh.run(),現在你會得到:

image

註意本例的輸出結果應該是4 tests to run in 1 groups,而非截屏中的8 tests。看起來這個例子並不太好,因為我們想看一下出現錯誤的情況。把被測試代碼中任意一個函數的實現改成錯誤的實現,比如,讓alwaysTrue返回false。再次重復上面的步驟,這次我們得到:

image

啊哈!沒有繁瑣的編寫HTML,部署和設置,略微做瞭一點hack,我們就有瞭一個可能是史上部署最快的DOH測試。

最後,完整的代碼附在附件中。你可以將文件打開,將代碼拷貝到firefox命令窗口中運行。註意在加載DOH後(文件的前兩行),要等一會兒才可以繼續運行餘下的代碼。

註:有時候測試會因為 runner.js(1.61版)第1299行的if(this._paused){ return; }導致測試中止且沒有結果輸出。可以將這一行註釋掉。在附件中該行已註釋。

 

CSDN不支持js的附件,請訪問http://www.lotus-scent.com/blog以獲取附件

 

摘自:盛夏蓮花- 前沿web技術

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *