doh robot及其单元测试框架简介

1 前言

目前单元测试作为保证软件质量的手段已经被越来越多的开发团队所重视。在Web开发中,Java的单元测试手段较多,基于Junit的工具层出不穷。但是对于前台的单元测试,优秀工具少之又少。目前比较出名的JS单元测试工具有Jquery推出的Qunit,dojo推出的doh,以及比较经典的jsunit。虽然对于界面的集成测试,工具较多。但是由于界面集成测试时间成本较高,对于持续集成来说,为了测试一个小的改动就要花费大量的时间去跑界面自动化测试用例显然不合实际。本文将对doh测试工具作一个初步介绍,包括其robot以及其单元测试框架。

2 doh robot简介

doh robot基于applet技术,屏蔽浏览器差异。通过Java代码产生的事件来源于浏览器外部,不同于JS“合成”的事件。这种事件是被浏览器所信任的;另外doh robot可以比较真实的模拟界面事件。比如鼠标单击,doh将先移动鼠标到目标位置再点击,这样一来其附加的mouseover,mouseout事件都会被触发。

2.1 三种doh robot

  • doh.robot

这种robot是不需要dojo支撑的,其余的两个robot都需要dojo功能支持

  • dojo.robot

扩展的doh.robot,doh.robot只支持将鼠标移动到某一个特定的位置,而dojo.robot支持将鼠标移动到一个指定的html节点

  • dijit.robot

扩展的dojo.robot,增强鼠标滚轮操作。这个用的一般比较少,我也没大看明白这个类的代码:(

2.2 API介绍

doh.robotAPI列表如下

  • sequence:function(/*Function*/ f, /*Integer, optional*/ delay, /*Integer, optional*/ duration)
  • typeKeys: function(/*String||Number*/ chars, /*Integer, optional*/ delay, /*Integer, optional*/ duration)
  • keyPress: function(/*Integer*/ charOrCode, /*Integer, optional*/ delay, /*Object*/ modifiers, /*Boolean*/ asynchronous)
  • keyDown: function(/*Integer*/ charOrCode, /*Integer, optional*/ delay)
  • keyUp: function(/*Integer*/ charOrCode, /*Integer, optional*/ delay)
  • mouseClick: function(/*Object*/ buttons, /*Integer, optional*/ delay)
  • mousePress: function(/*Object*/ buttons, /*Integer, optional*/ delay)
  • mouseMove: function(/*Number*/ x, /*Number*/ y, /*Integer, optional*/ delay, /*Integer, optional*/ duration, /*Boolean*/ absolute)
  • mouseRelease: function(/*Object*/ buttons, /*Integer, optional*/ delay)
  • mouseWheel: function(/*Number*/ wheelAmt, /*Integer, optional*/ delay, /*Integer, optional*/ duration)

看到函数的名字基本上都可以知道这个函数的功能,在分别介绍函数功能前,先介绍一下共有的参数delay和duration(这两个参数在所有的API中都是可选的):

这两个参数都是以毫秒为单位

delay:

delay起到的作用类似于setTimeOut函数。表示经过delay所定义的时间后,函数将被执行。该参数可以不输,默认500毫秒。

duration:

这个函数表示浏览器讲用掉这么长的时间来完成一个界面操作。比如doh.robot.typekeys('dij',500,1800)表示500毫秒后,robot将通过键盘键入dij三个字母,整个操作将维持1.8秒,1.8秒后执行后面操作。

对于所有的键盘操作,都要传入键盘值。对于数字或者字母键可以以字符串的形式传入typeKeys函数;对于功能键,可以加入用dojo定义的枚举类dojo.keys传入键盘Code比如doh.robot.keyPress(dojo.keys.ENTER, 1000, {});dojo.keys的代码位于dojo源码包中的dojo/_base/event.js中,其对应的代码片断为

dojo.keys = { // summary: definitions for common key values BACKSPACE: 8, TAB: 9, CLEAR: 12, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, PAUSE: 19, CAPS_LOCK: 20, ESCAPE: 27, SPACE: 32, PAGE_UP: 33, PAGE_DOWN: 34, END: 35, HOME: 36, LEFT_ARROW: 37, UP_ARROW: 38, RIGHT_ARROW: 39, DOWN_ARROW: 40, INSERT: 45, DELETE: 46, HELP: 47, LEFT_WINDOW: 91, RIGHT_WINDOW: 92, SELECT: 93, NUMPAD_0: 96, NUMPAD_1: 97, NUMPAD_2: 98, NUMPAD_3: 99, NUMPAD_4: 100, NUMPAD_5: 101, NUMPAD_6: 102, NUMPAD_7: 103, NUMPAD_8: 104, NUMPAD_9: 105, NUMPAD_MULTIPLY: 106, NUMPAD_PLUS: 107, NUMPAD_ENTER: 108, NUMPAD_MINUS: 109, NUMPAD_PERIOD: 110, NUMPAD_DIVIDE: 111, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, F7: 118, F8: 119, F9: 120, F10: 121, F11: 122, F12: 123, F13: 124, F14: 125, F15: 126, NUM_LOCK: 144, SCROLL_LOCK: 145 };

对于鼠标事件需要传入buttons对象,这个对象包含三个布尔型属性left、right、middle。表示鼠标按下的是左键,右键,滚轮,为true表示状态是按下,没有或者为false表示相反。举例doh.robot.mouseClick({left:true}, 500);

对于功能性代码的执行可以用sequence实现,可以参见第三节。

dojo.robot扩展的API为,可以支持鼠标定位到具体的html节点

mouseMoveAt : function(/*String||DOMNode||Function*/ node, /*Integer, optional*/ delay, /*Integer, optional*/ duration, /*Number, optional*/ offsetX, /*Number, optional*/ offsetY)

2.3 功能强大的record

 

该功能基于dojo,在测试页面加入dojo.require("dojox.robot.recorder"); 其功能就生效了,具体的操作步骤为

  1. 进入测试页面,在测试开始点键入ctrl+alt+enter,这个时候回弹出alert框,告诉用户开始录制
  2. 进行界面操作,直到测试用例结束
  3. 再次点击ctrl+alt+enter,出现对话框图层,测试代码自动生成,用户copy后在其基础上可以修改

 

3 举例

3.1 doh.robot测试代码举例

<html> <head> <mce:style><!-- @import "../robot/robot.css"; --></mce:style><mce:style mce_bogus="1"><!-- @import "../robot/robot.css"; --></mce:style><mce:style mce_bogus="1" mce_bogus="1"><!-- @import "../robot/robot.css"; --></mce:style><mce:style mce_bogus="1" mce_bogus="1" mce_bogus="1"><!-- @import "../robot/robot.css"; --></mce:style><mce:style mce_bogus="1" mce_bogus="1" mce_bogus="1" mce_bogus="1"><!-- @import "../robot/robot.css"; --></mce:style><style mce_bogus="1" mce_bogus="1" mce_bogus="1" mce_bogus="1" mce_bogus="1"> @import "../robot/robot.css";</style> <mce:script src="../runner.js" mce_src="runner.js"></mce:script> <mce:script src="../robot.js" mce_src="robot.js"></mce:script> </head> <body> <form> <input type="text" value="hi" id="textbox" style="position:absolute; left:0px; top:20px; font-family:system;"></input> </form> <mce:script type="text/javascript"><!-- doh.register("doh.robot",//定义测试套 { name:"dojorobot1",//定义测试用例 timeout:6900, setUp:function(){ document.getElementById('textbox').value="hi"; }, runTest:function(){ var d=new doh.Deferred(); doh.robot.mouseMove(30, 30, 500);//移动鼠标到指定坐标 doh.robot.mouseClick({left:true}, 500);//点击鼠标 doh.robot.typeKeys(" again", 500, 2500);//键入again doh.robot.sequence(function(){ if(document.getElementById('textbox').value=="hi again"){ document.getElementById('textbox').value += ": passed";//通过测试用例 d.callback(true); }else{ document.getElementById('textbox').value += ": failed"; d.errback(new Error("Expected value 'hi again', got "+document.getElementById('textbox').value));//错误 } }, 900); return d; } tearDown: function() { } }); doh.run(); // --></mce:script> </body> </html>

doh.robot不需要dojo支持,所以可以直接通过引入doh的robot.js来实现。界面上可以看到鼠标滑到30,30的位置,键入again通过测试用例

 

3.2 dojo.robot测试代码举例

dojo.require("dojo.robot"); dojo.addOnLoad(function(){ doh.register("doh.robot", { name:"dojorobot1", timeout:6900, setUp:function(){ document.getElementById('textbox').value="hi"; }, runTest:function(){ var d=new doh.Deferred(); doh.robot.mouseMoveAt(document.getElementById('textbox'),500); doh.robot.mouseClick({left:true}, 500); doh.robot.typeKeys(" again", 500, 2500); doh.robot.sequence(function(){ if(document.getElementById('textbox').value=="hi again"){ document.getElementById('textbox').value += ": passed"; d.callback(true); }else{ document.getElementById('textbox').value += ": failed"; d.errback(new Error("Expected value 'hi again', got "+document.getElementById('textbox').value)); } }, 900); return d; }, tearDown:function(){} }); doh.run(); });

doh需要dojo支持,不过定位节点的功能增强了

4 doh测试框架页面

doh提供了测试框架页面,提供类似于JUNIT测试的视觉效果. 其整合过程为

  • 我们和dojo的util目录建立同级目录demo,并在demo/doh/tests目录下编写测试框架页面,代码如下

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>demo.doh Unit Test Runner</title> <meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=demo.doh.tests.module&registerModulePath=../demo,demo"> </head> <body> Redirecting to D.O.H runner. </body> </html>

registerModulePath=../demo,demo定义了模块路径以及模块名称,其中模块名称为demo,路径为../demo,注意这里如果写相对路径,是相对 于连接页面../../../util/doh/runner.html的路径,而不是你所写的测试框架页的路径.其中testModel指定了测试模块定义文件,这里的文件遵循 dojo风格,就是路径分割符用.表示,由于模块路径demo被定义为../demo,所以这里的模块文件就demo对应的路径/doh/tests/module/js

其实这里的demo就是我们新建的demo目录,module.js和测试框架页面在同一个目录下.

  • module.js其实就是一个测试模块列表

dojo.provide("demo.doh.tests.module"); //This file loads in all the test definitions. try{ //Load in the widget tests. dojo.require("demo.doh.tests.widgets.DemoWidget"); }catch(e){ doh.debug(e); }

module.js定义了需要加载的测试模块demo.doh.tests.widgets.DemoWidget

  • 测试模块定义JS demo.doh.tests.widgets.DemoWidget

dojo.provide("demo.doh.tests.widgets.DemoWidget"); if(dojo.isBrowser){ //Define the HTML file/module URL to import as a 'remote' test. doh.registerUrl("demo.doh.tests.widgets.DemoWidget", dojo.moduleUrl("demo", "doh/tests/widgets/DemoWidget.html")); }

该函数指定了测试页面DemoWidget.html,只要在测试页面中写入我前面所描述的测试代码,就可以运行单元测试了

5 常见问题分析

5.1 运行applet出现不能加载jvm.dll错误:

1. 删除所有JRE;

2. Windows系统 系统盘c盘:

在目录 “C:/Documents and Settings” 下有三个文件夹(或许你不全有,没有关系):

“All Users.WINDOWS”

“Default User”

还有一个是你自己的用户名

每个目录下都有结构

/Application Data/

/Local Settings/Application Data

在这两个目录下有SUN目录一律删除;

3. 最后安装你想要安装的JRE,重新启动电脑即可!

5.2 执行typekey函数没有输入

使用随dojo1.2.1以上版本发布的doh,并且保证在你的浏览器窗口中输入法是关闭的

 

你可能感兴趣的:(doh robot及其单元测试框架简介)