前端自動化測試工具doh學習總結(二)


  一、robot簡介

  robot是dojo框架中用來進行前端自動化測試的工具,doh主要目的在於單元測試,而robot可以用來模仿用戶操作來測試UI。總所周知,Selenium也是一款比較流行的前端自動化測試工具,與Selenium相比robot的優點在於robot觸發的瀏覽器事件是真正的用戶操作事件,而Selenium中的事件屬於“合成事件”。打個比方,用戶在一個textbox元素上觸發了mousedown事件,但是在觸發mousedown事件之前,肯定會觸發mouseover等事件。如果使用Selenium的工具的“合成事件”則不會觸發mouseover等事件。對於使用dojo框架的開發者來說,robot更有利於同dijit交互,包括自定義dijit;當然最重要的一點是,在研究selenium的過程中,我發現Selenium有嚴重的瀏覽器兼容性問題!於是果斷放棄。

  言歸正傳,下面來具體介紹robot。robot主要有三部分組成:

  doh/robot,這里面包含的是robot的核心內容,與dojo框架沒有耦合關系,可以單獨拿出去作為一個自動化測試工具。

1 require(["doh/robot"], function(doh){
2     ...
3 });

  dojo/robot,該模塊使用dojo核心技術,支持doh/robot的全部方法,主要在doh/robot的基礎上增加了兩個方法:mouseMoveAt和scrollIntoView。

1 require(["dojo/robot"], function(doh){
2     ...
3 });

  dojox/robot,該模塊在dojo/robot的基礎上增加了兩個重要方法:initRobot和waitForPageLoad。為什么說他們重要,因為他們可以再一個測試案例文件中控制其他的測試文件,后文將詳細。

1 require(["dojox/robot"], function(doh){
2     ...
3 });

  

  二、基本步驟

  doh/robot測試主要分為以下四步:

  1、實例化一個doh.Deferred對象

  2、執行交互命令

  3、設置一個超時函數來驗證交互結果

  4、在runTest中返回deferred對象

  這個事例中頁面上一個文本輸入框,包含hi兩個字符,然后模仿用戶輸入“ again”動作。示例,robot實際上是一個applet第一次訪問的話會提示安裝。

 1 require(["doh/runner", "doh/robot"], function(doh, robot){
 2     doh.register("doh/robot",
 3     {
 4         name: "dojorobot1",
 5         timeout: 6900,
 6         setUp: function(){
 7             document.getElementById('textbox').value="hi";
 8         },
 9         runTest: function(){
10             var d = new doh.Deferred();
11             robot.mouseMove(30, 30, 500);
12             robot.mouseClick({left:true}, 500);
13             robot.typeKeys(" again", 500, 2500);
14             robot.sequence(d.getTestCallback(function(){
15                 doh.is("hi again", document.getElementById('textbox').value);
16             }), 900);
17             return d;
18         }
19     });
20     doh.run();
21 });
    <form>
    <input type="text" value="hi" id="textbox" style="position:absolute; left:0px; top:20px; font-family:system;"></input>
    </form>

  這里要說以下robot.sequence和d.getTestCallback這兩個函數,sequence是robot中的一種同步方式書寫的setTimeout,下文delay中會講到這類方法的優勢。doh.Deferred是doh中對dojo/Deferred的擴展,加入了許多方法,getTestCallback就是其中之一,該函數作用就在於交互命令執行完成后驗證交互結果,並將結果告知測試框架從而決定顯示綠條還是紅條,通常一個測試案例中只有一處調用該方法。一下是該函數的源碼:

 1 getTestCallback: function(cb, scope){
 2         var _this = this;
 3         return function(){// 該函數返回一個閉包給sequence函數,從而在一定時間后調用該閉包
 4             try{// 執行驗證函數,監控結果,並將結果通知測試框架
 5                 cb.apply(scope||doh.global||_this, arguments);
 6             }catch(e){
 7                 _this.reject(e);// 紅條
 8                 return;
 9             }
10             _this.resolve(true);// 綠條
11         };
12     },

  

  三、API介紹

  1、基本參數

  下面以doh/Robot中typeKeys為例介紹一下robot API的基本參數,具體提供了哪些API可以在這里查看:API

 1 typeKeys: function(/*String||Number*/ chars, /*Integer, optional*/ delay, /*Integer, optional*/ duration){
 2       // summary:
 3       //            Types a string of characters in order, or types a dojo.keys.* constant.
 4       //
 5       // description:
 6       //           Types a string of characters in order, or types a dojo.keys.* constant.
 7       //           Example: robot.typeKeys("dijit.ed", 500);
 8       //
 9       // chars:
10       //            String of characters to type, or a dojo.keys.* constant
11       //
12       // delay:
13       //            Delay, in milliseconds, to wait before firing.
14       //            The delay is a delta with respect to the previous automation call.
15       //            For example, the following code ends after 600ms:
16       //                  robot.mouseClick({left:true}, 100) // first call; wait 100ms
17       //                  robot.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
18       //
19       // duration:
20       //            Time, in milliseconds, to spend pressing all of the keys.
21       //
22   }

  delay,顧名思義目的在於延遲,在webAPP中經常會有動畫效果,等待動畫結束后在執行click等事件,所以每一個API中與UI交互的函數都會提供這個方法。該方法內部使用setTimeout方法實現,既然這樣,為什么不讓用戶直接使用setTimeout方法?原因在於dojo可以為我們自動調整一系列動作的執行順序及間隔。舉個例子,如果使用setTimeout,動作f1需要在300ms后執行,動作f2需要在f1之后100ms執行那就需要設置f2的timeout時間為400ms,這時候f1之前要加一個動作f3在f1之前200ms執行,

現在我們就需要挨個該f1跟f2的時間參數,如果f1之后有100個動作要執行。。。。God bless you。使用robot API提供的函數,我們只需要設置每個動作之間的時間間隔即可。

1     setTimeout(f1, 300);
2     setTimeout(f2, 400);
3     =>>
4     setTimeout(f3, 300);
5     setTimeout(f1, 500);
6     setTimeout(f2, 600);    
1     var mask = query("div.ovwHighlight")[0];
2     robot.mouseMoveAt(mask, 200, 200);
3     robot.mousePress({left: true}, 100);
4     robot.mouseMoveAt(mask, 200, 200, 10, 10);
5     robot.mouseRelease({left: true}, 100);        

  duration便是的是執行這個動作所需要的時間,以typeKeys為例,假設duration設置為1800ms,char為“abc”,則輸入a、b、c這三個字符各占600ms。

  2、mouseMoveAt

  dojo/Robot中提供了一個mouseMoveAt函數,在上文的示例中,我們可以看到鼠標移動函數用的是mouseMove函數,該函數與mouseMoveto函數都是通過相對於當前瀏覽器document的x、y坐標來定位元素,而mouseMoveAt則是通過選擇符或者node節點來定位元素。

 1 mouseMoveAt : function(/*String||DOMNode||Function*/ node, /*Integer, optional*/ delay, /*Integer, optional*/ duration, /*Number, optional*/ offsetX, /*Number, optional*/ offsetY){
 2     // summary:
 3     //            Moves the mouse over the specified node at the specified relative x,y offset.
 4     //
 5     // description:
 6     //           Moves the mouse over the specified node at the specified relative x,y offset.
 7     //           You should manually scroll off-screen nodes into view; use dijit.robot for automatic scrolling support.
 8     //           If you do not specify an offset, mouseMove will default to move to the middle of the node.
 9     //           Example: to move the mouse over a ComboBox's down arrow node, call doh.mouseMoveAt(dijit.byId('setvaluetest').downArrowNode);
10     //
11     // node:
12     //            The id of the node, or the node itself, to move the mouse to.
13     //            If you pass an id or a function that returns a node, the node will not be evaluated until the movement executes.
14     //            This is useful if you need to move the mouse to an node that is not yet present.
15     //
16     // delay:
17     //            Delay, in milliseconds, to wait before firing.
18     //            The delay is a delta with respect to the previous automation call.
19     //            For example, the following code ends after 600ms:
20     //                  doh.mouseClick({left:true}, 100) // first call; wait 100ms
21     //                  doh.typeKeys("dij", 500) // 500ms AFTER previous call; 600ms in all
22     //
23     // duration:
24     //            Approximate time Robot will spend moving the mouse.
25     //            The default is 100ms.
26     //
27     // offsetX:
28     //            x offset relative to the node, in pixels, to move the mouse. The default is half the node's width.
29     //
30     // offsetY:
31     //            y offset relative to the node, in pixels, to move the mouse. The default is half the node's height.
32     //

  所以上文中的實例可以這樣寫:

 1 require(["doh/runner", "dojo/robot"], function(doh, robot){
 2     doh.register("doh/robot",
 3     {
 4         name: "dojorobot1",
 5         timeout: 6900,
 6         setUp: function(){
 7             document.getElementById('textbox').value="hi";
 8         },
 9         runTest: function(){
10             var d = new doh.Deferred();
11             robot.mouseMoveAt(document.getElementById('textbox'), 500);
12             robot.mouseClick({left:true}, 500);
13             robot.typeKeys(" again", 500, 2500);
14             robot.sequence(d.getTestCallback(function(){
15                 doh.is("hi again", document.getElementById('textbox').value);
16             }), 900);
17             return d;
18         }
19     });
20     doh.run();
21 });

  3、initRobot

  對於WebAPP來說,都需要將測試代碼與主程序代碼分離。但測試文件執行時需要與主程序中的UI交互,這時輪到initRobot閃亮登場了。該函數位於dojox/Robot中,所以我們需要引入dojox/Robot。initRobot主要的作用就在於將當前測試文件的執行環境轉變為主程序環境,這時robot.doc、robot.window代表的則是主程序中的document和window。比如說你想使用document.getElementById(‘login')來獲取主程序中的login元素,那么你需要這樣來寫robot.doc.getElementById('login'),官方文檔中提到使用dojo模塊中的方法的執行環境都是主程序環境,遺憾的是我在實際使用中發現並非如此,有的模塊方法的確是主程序環境比如query,而有的則並非主程序環境比如registry。

  具體示例可以訪問這里,查看源碼你會發現這里面並沒有robot的測試代碼,該文件位於dojo-release-1.9.1-src\dijit\tests目錄下,robot測試代碼位於dojo-release-1.9.1-src\dijit\tests\robot目錄下。

 

參考文檔:https://dojotoolkit.org/reference-guide/1.9/util/dohrobot.html#doh-robot

下一篇我們將具體看一個完整robot示例,以及將robot與selenium聯合使用進而將他與CI工具集成。同時我們還會討論robot異步函數的美中不足。


免責聲明!

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



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