最近在学软件qtp自动化测试实践,想知道qtp 软件下载那个版本比较好

我是女孩子现在即将去达内学习软件方面的知识,软件测试和JAVA 想知道对于学成出来工作哪个好找工作_百度知道
我是女孩子现在即将去达内学习软件方面的知识,软件测试和JAVA 想知道对于学成出来工作哪个好找工作
求大神解答这俩个学成率 还有学成就业 薪资等方面的,,,谢谢了,迷茫期真的天天心焦~还有达内学习怎么样。
提问者采纳
软件测试不太费脑,待遇也不高,从业的女孩比较多,也更好学。学java费脑,我就是搭配培训的java,同期的几个女孩子最后都没有学成,没有从事开发工作,不知道学完干嘛去了。和我一样的一些走投无路的同学可能比较努力,最后学成了,也走上了这条道路。达内学习我个人感觉是比较坑的,不过放眼国内似乎都这个德行,达内好歹名气比较大一点。其实只要你够努力,达内能学到的东西都能在网上学到,只是对于没有软件学历的人来说,有个培训证书也好找工作一点。努力一把,工资不要开太高,是可以走上这行的,混点工作经验跳个槽,工资就涨起来了。
测试的工资大概多少?初期 中期的。 还有你说达内有点坑?他们跟我说学完工资扣学费的,不知道是不是真的。
测试我知道一个女孩是3500她说她还不会工具,我没搞过测试,也不明白什么是测试工具,软件开发一开始工资和这个差不多,不过一般2年过5K,4年过万的节奏。我的是工资扣学费。感觉划不来,还不如一次交清比较划算,当时一次交清是12800,我贷款工资一个一个月扣差不多一共扣了15800.
你是达内出来的?
是的,广州达内,个人感觉深圳的好一点。我一个同学深圳达内,他已过万了。
提问者评价
其他类似问题
按默认排序
其他4条回答
JAVA的工作岗位肯定比测试的多,但是一般开发的都不喜欢收女生。薪资的话,开发一般都要高于测试。
测试好找工作吗。工资大概在?
首先,你先要问问自己,对什么有兴趣,李涛老师讲过,兴趣是学习最好的老师,只有你对一门技术特别的感兴趣,你才能投入到其中快乐的学习,这样你的学习才是进步的,有用的,要是你都不知道你自己喜欢哪方面,可能没有学习一个月就会放弃,这样可是得不偿失的啊,关于这两个专业可以说都是不错的方向,java方面的现在的需求还是非常多的,毕业之后找工作也比较容易,学习起来也行,只要用心,跟上项目还是可以的;关于测试,现在的软件公司现在也越来越注重这方面了,对这方面的需要也越来越多了,对于女生来说,我个人建议是学软件测试,应为这个逻辑思维要求不是太高,相信一般人还是能完全应对的!不过前提要看你自己的选择了,我们只能给你一个建议
苏杭那块听说现在还不错
你去学习哪个版块的?
软件测试。
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁您现在的位置: &
QTP无法录制某些控件的操作的解决方法
QTP无法录制某些控件的操作的解决方法
  经常有朋友问:QTP无法识别某些自制的控件或无法录制某些控件的操作,我怎么解决这个问题? 我想解决方法有下面几个:
  1 添加相应的Add-in是解决此类问题的第一选择,如果有相应的Add-in的话。例如如果是测试 Java 类的程序,就要加载 Java Add-in。  你安装好 QTP后,有三个Add-in ( ActiveX、Visual Basic和 Web)就被装载了。除此以为,QTP 8.2 版本还可以装载的 Add-in 有& QuickTest Professional& Java 6.5 Add-in 、QuickTest Professional Oracle 6.5 Add-in 、QuickTest Professiona Siebel 8.0& Add-in 和 QuickTest Professional Terminal Emulator 8.0 Add-in。 (每个版面的QTP可以加载的 Add-in 可以在相应的QTP_Install_Guide.pdf 和 Main_Users_Guide.pdf 中找到。)
  2 把不能识别的对象设置为虚拟对象(Virtual Object)  依次点击 QTP 的 “Tools” ---& "Virtual Objects"---&"New Virtual Object...", 就会出现 Virtual Object Wizard 对话框,你根据Wizard& 的指引,就可以把添加一些支持的不好的控件设置成虚拟控件,也就添加到对象库了。
  CODE:[Copy to clipboard]&& 在QTP 8.2 添加虚拟对象的具体操作步骤是:&&&&&& 1,& 依次点击 Tools ---& Virtual Objects ---& New Virtual Object…,打开虚拟对象向导,点击Next;&&&&&& 2,& 选择Class为button,点击Next;&&&&&& 3,& 点击标记对象按钮;&&&&&& 4,&& 选择要操作的对象区域,点击Next (对象区域就是你要操作的那个对象,就是login按钮);&&&&&& 5,&&& 默认,点击Next;&&&&&& 6,&& 完成。
  3 针对特殊问题有特殊的解决方法。如果不能识别的控件是用VC做的,那么你可以自己写一个动态链接库,然后让QTP去调用它。至于QTP 如何调用动态链接库,请看附件。
  如果谁还有好方法,请也说出来。大家一起讨论一下。我坚信这里问题一定能得到解决!胜利一定是属于我们的!
&&&主编推荐
&&&热门试卷
&&&最新视频
&&&热门阅读
&&&最新问答
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&增值电信业务经营许可证湘B2-您现在的位置: &
使用 Abbot 框架自动化测试 Eclipse 插件的用户界面
使用 Abbot 框架自动化测试 Eclipse 插件的用户界面
  如今 Eclipse RCP 平台已成为 Java 平台上的富客户端首选,而 SWT 和 JFace 的高效率也让诸多 Java 界面开发者受益匪浅。在插件化已经成为一种潮流的今天,我们迫切需要一种自动化的界面测试工具去测试 Eclipse 的插件。Abbot 框架就是这样一种自动化的UI测试工具,它提供了一系列的能够执行 Swing 或者 SWT 界面测试的 API,并提供了脚本录制和编辑、运行的工具。Abbot 的 SWT 版本是基于 Eclipse 的插件形式发布的,天然的支持了 Eclipse 插件的自动化测试。  本文详细的描述了 Abbot SWT 插件的配置和使用,分析了 Abbot 的体系结构和工作原理,并给出复杂的测试用例来说明 Abbot SWT 的一些高级用法,同时还分享了作者的一些 Abbot 相关的最佳实践,相信会对从事 Eclipse 插件和 SWT 用户界面的开发和测试人员有一定的帮助。  引言  从 JDK 1.3 以来新增加的一个特性就是对图形用户界面自动化测试的支持,通过使用 Java.awt.Robot 类和相关的功能,程序员可以调用 JDK 的 API 可以直接实现用户界面的操作,常被用作用户界面的自动化测试,但是这些底层的 API 使用起来不是很方便,所以 JFCUnit 和 Jemmy 等测试工具都对 Java.awt.Robot 进行了包装,能够在 API 级别直接支持 AWT 和 Swing 的用户界面测试。但是到目前为止,它们尚不支持 SWT。SWT 作为 Eclipse 插件界面开发的首选,正日趋完善和流行,因此大量的程序员在开发 Eclipse 插件和 SWT 的用户界面时,往往需要千百次的点击鼠标去重复的测试图形用户界面,繁琐而且效率低下。  幸运的是,我们有 Abbot,一个可以自动化的测试 SWT 和 Eclipse 插件用户界面的测试框架。Abbot 是
站点上的一个优秀 Java GUI 测试框架,最初主要支持 AWT 和 Swing 的用户界面自动化测试,后来随着 SWT 的流行,就增加了对 SWT 的支持。为了与 Eclipse 更为紧密的集合,Abbot 目前已经以 Eclipse 插件的形式开发,Abbot 对 SWT 的支持是通过 Abbot SWT 插件来实现的。目前 abbot 的 SWT 插件尚未正式发布,我们将指引你从 CVS 上获取一个可用版本,目前的代码已经能够支持绝大多数的 SWT 和 JFace 构件的测试。笔者在一个项目中使用了数十个基于 Abbot 的 UI 测试用例,效果良好。实践证明,在 Eclipse RCP 和插件项目中,通过 Abbot 和 JUnit 的结合,构建用户界面的自动化测试用例,可以极大的减少测试人员重复的用户界面测试工作。  本文将带领读者走入 Abbot 的世界,学习使用这一有力的工具来增加我们插件开发的工作效率,在全面的介绍Abbot之前,我们先从一个简单的测试用例,感受一下 Abbot 的非凡魅力。  新手上路:开始一个简单的 Abbot SWT 测试  这一部分将介绍 Abbot SWT 插件的下载和配置,给出一个简单的测试用例使读者对 Abbot SWT 有个感性的认识,然后通过分析该测试用例来介绍 Abbot 的基本概念,使读者能够“观其大略”。本文所有的示例代码都在 Eclipse 3.2.1,JDK1.5 和 JUnit3.8.1 环境下通过测试,请读者先准备好开发环境。  Abbot plugin 测试环境配置  目前 Abbot SWT 的插件尚在开发过程中,没有可用的发行版本,我们将从 CVS 上获取源码。首先启动 Eclipse,指定一个新的空白的 WorkSpace,配置 Abbot 的 CVS 仓库,具体配置信息参见 图 1,使用匿名用户,无需输入密码即可。  图 1:Abbot 项目的 CVS 配置信息  点击确定以后打开 CVS 仓库的 HEAD,同时选中 abbot、abbot.swt 和 abbot.swt.eclipse 三项,点击右键,在弹出菜单中选择“check out”,下载被选中的三个插件项目。  切换到 PDE 透视图,你可以看见 WorkSpace 中的三个 Eclipse 插件,其中 abbot 插件是基础的插件,具有 Abbot 的基础功能和 AWT/Swing 的界面测试功能;abbot.swt 插件是在 abbot 基础上的扩展,增加了对 SWT 的支持;而 abbot.awt.eclipse 则在 abbot SWT 的基础上增加了对 Eclipse 插件测试的支持,比如一些常用的针对 Eclipse 的实用工具、JFace 对话框的测试支持等。  视你的 Eclipse 的环境不同,你可能需要做一定的配置才能保证编译通过,请不要介意那么多的 warning,因为你使用的是正在开发中的源代码。为了便于读者使用,笔者在附件中也附加了这三个插件及其源码,读者也可以直接下载,然后导入到 Eclipse 工作区中。  现在你的工作区中的三个项目已经通过编译了,下面我们将用一个简单的例子来展示 Abbot SWT 的用法和基本概念。  开发一个简单的测试用例
  为了简化步骤,我们的测试用例将简单的测试 Eclipse 的新建 Java 类向导,这样做可以避免我们编写被测试代码。我们将创建一个测试插件,并在该插件中创建一个测试用例来执行新建 Java 类向导的界面测试。你可以遵循以下步骤来创建和运行该测试用例。
  1. 创建测试插件
  在刚刚配置好的包含 Abbot 插件的工作区中新建一个插件项目,命名为 AbbotTest,所有选项采用默认设置,给该插件增加如图 2 的 Dependency:
  图 2: AbbotTest 插件的 Dependencies
  &&&&请确认选用了 JUnit 的 3.8.1 版本,使用更高版本的 JUnit 可能会引起一些问题,本文的测试用例在 JUnit 3.8.1 版本上能够通过所有测试。
  2. 在测试插件中创建测试用例
  在该插件中新建一个 Java 类,类名为 JavaWizardTest,包名为 abbottest.sample,该类的 Java 代码如表 1 所示。
  清单 1. JavaWizardTest.java 的代码package abbottest.import junit.framework.TestC
  import org.eclipse.swt.widgets.Bimport org.eclipse.swt.widgets.Dimport org.eclipse.swt.widgets.MenuIimport org.eclipse.swt.widgets.Timport org.eclipse.swt.widgets.W
  import abbot.finder.matchers.swt.ClassMultiMimport abbot.finder.matchers.swt.TextMimport abbot.finder.matchers.swt.TextMultiMimport abbot.finder.swt.BasicFimport abbot.finder.swt.TestHimport abbot.tester.swt.ButtonTimport abbot.tester.swt.MenuItemTimport abbot.tester.swt.Rimport abbot.tester.swt.TextTimport abbot.tester.swt.WidgetT
  public class JavaWizardTest extends TestCase {public void testJavaWizard() {final Thread wizMain = new Thread() { &&& public void run() { &&&&& WidgetTester.waitForShellShowing( "New Java Class");&&&& findAndTestWizard(); &&&& } &&& }; &&& wizMain.start(); &&& openJavaWizard(); & }
  private void openJavaWizard() {&& MenuItemTester menuItemTester = (MenuItemTester) WidgetTester.getTester(MenuItem.class);&& menuItemTester.actionSelectMenuItem( "&File/&New\tAlt+Shift+N/Class",null, &&& Display.getCurrent().getActiveShell(), 1000); & }
  private void findAndTestWizard(& ) {&& TestHierarchy hierarchy = new TestHierarchy(Display.getCurrent());&& final BasicFinder finder = new BasicFinder(hierarchy); && try { && final Widget root = finder.find(new TextMatcher( "New Java Class"));&&& final Text nameText = (Text) finder.find(new ClassMultiMatcher(Text.class, 4)); &&& final Button finishButton=(Button)finder.find(root, &&&v new TextMultiMatcher( "&Finish",1,Button.class));&&& final& Button cancelButton=(Button)finder.find(root, &&&& new TextMultiMatcher( "Cancel",1,Button.class));& & abbot.tester.swt.Robot.syncExec(root.getDisplay(), null, new Runnable() { && && public void run() { & &&&&& TextTester textTester = new TextTester(); &&&&& textTester.actionEnterText(nameText, "classname");&&&&& ButtonTester buttonTester= new ButtonTester(); &&&&& Robot.delay(1000); &&&&& assertFalse(finishButton.isEnabled()); &&&&& buttonTester.actionClick(cancelButton); &&&& } &&& }); && } catch (Exception e) { &&& e.printStackTrace(); &&& fail(e.getMessage()); && } & } }&
  从清单 1 中我们可以看出,JavaWizardTest.java 就是一个普通的 JUnit 测试用例,不过在测试方法里面使用了不少 Abbot 的 API。以上代码可以简单地演示如何测试 Eclipse 的新建 Java 类向导的一些特性,它使用到了 Abbot 提供的一些测试类,并通过启动新的 UI 线程对用户界面进行测试。具体代码的含义,我们将在下文介绍,这里主要希望运行这个测试用例来快速展示一下 Abbot SWT 的简洁用法。
  3. 运行该测试用例
  在“Package Exploer”视图中右键选中 JavaWizardTest.java,在右键菜单中选择“Run As -& JUnit Plug-in Test”,静静等待片刻。你将看见在新启动的 Eclipse Runtime 界面中,我们的测试用例自动的打开了新建 Java 类向导,并执行了我们预先定义的操作,输入一个类名,JUnit 执行断言,断言通过,取消该向导,测试成功。整个测试过程简单而快速,如果手工去做,可能需要点击多次鼠标和键盘,对于实际应用中复杂的用户界面,重复的手工劳动就不堪胜任。使用 Abbot,你可以轻松地重复执行标准化的测试,这正是自动化测试工具的优点。
  以上的例子让我们了解到 Abbot 的用法也是相当简单的,我们只需要在 JUnit 测试用例中增加 Abbot API 的调用,就能捕获界面上的构件(Widget),通过 Abbot API 我们可以触发界面动作,获取用户界面的执行结果,并作出断言来判断界面的运行是否符合我们的期望。就是这个简单测试用例,涵盖了大部分的 Abbot 的基本概念和框架的主要用法,下面我们会逐一介绍。  Abbot 基本概念
  我们将通过对以上测试用例的分析来向读者展示 Abbot 的基本概念,首先从最简单的部分入手来考察以该测试用例,我们选择 openJavaWizard 方法作为入手点,该方法使用了 MenuItemTester 类的 actionSelectMenuItem 方法,MenuItemTester 是 Abbot 众多的 Tester(我们称之为测试器)的一种,我们称为菜单项测试器,菜单项测试器的 actionSelectMenuItem 方法能够激活菜单栏的菜单项,就像我们鼠标选择该菜单项一样。根据我们的路径参数“&File/&New\tAlt+Shift+N/Class”,菜单项测试器找到我们期望的菜单项 --“新建 Java 类”菜单,从而打开“新建 Java 类”的向导。这里需要注意的是不同版本的 Eclipse 或者不同的透视图下,菜单项的路径是会不一样的,在笔者的 Eclipse 3.2.1 环境中,菜单项如 图 3 所示,因为 Abbot 完全是依赖文本的匹配去寻找 UI 构件,因此,其他情况下以此类推。
  图 3. Eclipse 3.2.1 的菜单项
  &&& 基于 图 3 的菜单项,我们菜单路径中的第二项子菜单才会出现“&New\tAlt+Shift+N”这样的路径,如果读者运行测试时在该方法内遇见“Widget not found ”或者超时的错误,你可能需要检查一下 Eclipse Runtime Workbench 的菜单是否和代码一致(不同版本的可能略有不同),如果不一致,稍加修改菜单项的路径参数就能使测试通过。
  这里我们接触到的第一个概念就是 Abbot 的 Tester,我们称之为测试器,测试器用于执行不同的 UI 构件测试,可以用于触发 UI 构件的相应动作,效果和使用鼠标操作界面一样,只不过是由代码触发,这样就可以在测试代码中控制用户界面的行为,达到用户界面自动化测试的目的。如 清单 1 所示,通过使用菜单项测试器,openJavaWizard 方法中简单的两行代码就能打开我们需要测试新建 Java 类向导。
  下面再看测试代码的主体部分,也就是 testJavaWizard 方法,读者也许奇怪该方法中代码的写法,我们将其摘录在 清单 2 中。
  清单 2:testJavaWizard 的方法体final Thread wizMain = new Thread() {& public void run() { && WidgetTester.waitForShellShowing( "New Java Class");&& findAndTestWizard(); & } };wizMain.start();openJavaWizard();&
  该方法之所以要使用线程,并且使用一种先等待,后触发的怪异方式,主要是因为 SWT 要求对 UI 的操作在新的线程中进行,同时 Eclipse 会启动新的 UI 线程来打开向导,我们很难保证打开向导后刚好能够执行后续的操作,也就很难保证顺序地同步地执行 UI 的测试。使用这种特有的“等待-触发”方式,就能保证测试的顺序满足我们的需求。以上代码展示了我们先启动一个测试线程在等待一个名为“New Java Class”的 shell(也就是新建 Java 类向导),然后执行 openJavaWizard 方法,一旦该方法能打开向导,等待线程就能捕获到,自然就会执行 findAndTestWizard 方法进行对向导的测试。启用线程等待对话框或者向导,然后执行对他们的测试是使用Abbot 时非常常用的一种方法,我们会频繁的在测试方法中使用这样的代码结构。默认情况下,线程的执行是同步的,所以我们不用担心测试用例会在线程运行结束前结束。
  了解这一点之后,我们就可以看看findAndTestWizard方法是如何进行测试,如同方法名所暗示的那样,它会先在界面上找到一些UI构件,然后测试这些构件。该方法的前两句(见 清单 3)是初始化一个BasicFinder,这是Abbot的数个Finder中的一种。Finder,我们称为查找器,它需要和匹配器(Matcher)一起协同工作,查找器和匹配器相配合就能在给定的UI阶层体系中寻找到目标构件。
  清单3:新建一个查找器TestHierarchy hierarchy = new TestHierarchy(Display.getCurrent());final BasicFinder finder = new BasicFinder(hierarchy);&
  通过清单 3 的代码我们生成一个查找器,通过查找器我们可以找到相应的用户界面的构件,如清单4的代码所示。
  清单 4:使用查找器查找 UI 构件final Widget root = finder.find(new TextMatcher("New Java Class"));final Text nameText = (Text) finder.find(new ClassMultiMatcher(Text.class, 4));final& Button finishButton=(Button)finder.find(root,& new TextMultiMatcher( "&Finish",1,Button.class));final& Button cancelButton=(Button)finder.find(root,& new TextMultiMatcher( "Cancel",1,Button.class));&
  找到界面上的构件,就可以让这些构件执行相应的动作,这就需要用到相应构件的测试器,在表 x 所示的测试代码中,我们首先创建文本测试器,然后可以在找到的文本框中输入文本,并创建按钮测试器,判断完成按钮是否被 Disable,然后我们取消该向导,代码如 清单 5。
  清单 5:对向导用户界面的测试代码& TextTester textTester = new TextTester(); & textTester.actionEnterText(nameText, "classname");& ButtonTester buttonTester= new ButtonTester(); & Robot.delay(1000); & assertFalse(finishButton.isEnabled()); & buttonTester.actionClick(cancelButton); &
  用户界面测试的常见的形式包括要判断构件是否正确生成、构件的状态和动作是否符合预定的需求、构件的数据是否满足测试的要求等等。
  需要注意的是,SWT 对在线程中访问UI构件有特殊的要求,而我们的测试代码是在一个线程中访问UI的构件,我们需要将这些代码置于 Runnable 的 run 方法体内通过 abbot.tester.swt.Robot.syncExec执行, 否则会抛出“Invalid thread access”的异常。至于“Robot.delay(1000);”这条语句,主要是保证一定的延时,因为 Abbot 的测试执行过快,如果测试者希望亲眼看着测试一步一步的进行,就可能需要多增加一些这样的语句。
  此时重新品味一下测试代码,你也许会不以为然(如果你能耐心读完本文,你就不会这样想),Abbot的用法非常的简单,无非是找到一些代测试的构件,执行相关的动作,比较测试的结果,这有何难?实际上这个例子是我们为了演示经过简化的,以上的测试代码虽然很简单,如果组合使用这些简单的逻辑,就能够测试很复杂的界面。就像你为所有重要的功能编写了单元测试一样,我们建议你为所有重要的界面编写测试用例,尤其对于一些数据敏感的动态生成的用户界面,Abbot的测试非常重要。
  但是,我们不推荐像单元测试一样写纯界面的测试,在单纯测试UI的同时,你可以通过UI的动作来测试业务逻辑,通过端到端的测试用例来实现业务功能的测试,除了自动化程度高以外,还可以避免代码的改变和业务逻辑的改变带来的测试用例的改变。对于一个设计良好的Eclipse插件,核心的用户界面的变化频率应该远远的低于业务逻辑的变化,因此通过界面去测试业务逻辑是很好的一种选择。选择重要的流程,通过Abbot构建端到端的测试用例,能够覆盖到绝大多数的业务流程,这样的测试能够很好的测试系统的业务功能,并极大的减少重复劳动,提高测试的效率。如果读者使用Eclipse平台开发过RCP业务系统,一定会深有这样的体会。
  在深入的掌握 Abbot 的复杂用法之前,我们先来读读 Abbot 的代码,研究一下 Abbot 的原理,这样做符合一个 XP 程序员的风格。  抽丝剥茧:Abbot SWT 的体系结构和工作原理
  通过以上的测试用例和概念介绍,你一定已经对 Abbot SWT 有了感性的认识,一个看似简单的测试用例,实际上并不简单,几乎包含了 Abbot 的所有主要内容。现在让我们继续深入下去,看看 Abbot SWT 的体系结构和工作的原理,以便更深刻的了解、掌握和使用它。
  Abbot 测试器
  我们首先从 Abbot 测试器开始,Abbot 测试器可以帮助我们对各种不同的UI构件进行测试,JavaWizardTest 测试用例使用到了文本测试器(TextTester)、按钮测试器(ButtonTester)、菜单项测试器(MenuItemTester)和通用的构件测试器(WidgetTester)。Abbot 为几乎所有的 SWT 构件提供了相应的测试器,我们可以从图 4 上看到这一点。
  图 4:Abbot 提供的所有的 SWT 部件的测试器
  &&&&&& 从图 4 可以看出,Abbot SWT 的测试器相当的丰富,仅有少数的复合构件及 JFace 构件如 Section、Browser、Dialog 等没有测试类。但是这些复合构件都是由基本的UI构件组成的,我们可以通过简单的UI构件的测试完成符合构件的测试。当然你可能需要研究这些构件的源代码,才能找到组成他们的基本构件,从而使用相应的测试器对其进行测试。例如 对于Section,这个复杂的UI构件,目前Abbot并没有提供“SectionTester”,但Section的标题栏实际上是一个Label, 你可以使用查找器根据Section的标题找到Label,然后调用 LabelTeseter的测试方法actionClick来打开或者关闭一个Section,有兴趣的读者可以试试,这是笔者在实际项目中遇到的一个小问题,其他的问题可以类似的方法解决。
  ??????? 和几乎所有的JavaGUI 测试工具一样,所有的测试器最后都是通过java.awt.Robot的API去激活用户界面,我们可以通过查看Abbot SWT的源码,最终可以一直追溯到 java.awt.Robot 和RobotPeer,这正是JDK中里面为了方便界面测试提供给程序员的底层API,可见所有的Java图形用户界面测试工具无不是扩展自这个Robot。java.awt.Robot可以生成操作系统原生的事件和消息来创建自动测试,自运行的演示,或者出于其他目的需要让应用来控制鼠标和键盘,用途很是广泛,有兴趣的读者可以深入研究。
  Abbot 查找器和匹配器
  虽然通过测试器可以发出消息驱动UI测试的完成,但是如果没有查找器的帮忙,你很难获取到你要测试的构件的句柄。我们已经了解到Abbot主要是依靠查找器(Finder)和 匹配器(Matcher)去寻找测试目标,尽管他们在 Abbot的基础插件中已经有了实现,Abbot SWT插件还是要为SWT开发了专门的查找器和匹配器。我们可以通过图 5 了解Abbot SWT的查找器和匹配器的关系:
  图5 :Abbot SWT的查找器和匹配器
  如图,我们最常用的是BasicFinder和匹配器的配合,通过参数配置,BasicFinder可以支持广度优先和深度优先的查找。  如图 6,考虑到不同的需求,Abbot SWT提供了不同种类的匹配器,他们都实现了Matcher接口,如果有特别的需求,你也可以自行实现或者修改现有的匹配器的代码。
  图6:Abbot SWT的匹配器
  &&&&&&&&&&&&&& 图 6 中展示了很多不同用途的匹配器,我们经常会使用 ClassMultiMatcher 和 TextMultimatcher。如果我们仔细的看看代码就明白 Abbot 是如何能够找到目标构件的,打开 abbot.finder.swt.BasicFinder 类,我们会看见 Abbot 会遍历 Hierarchy 上面的所有 UI 构件,直到找到匹配器的条件满足的构件返回。匹配器是如何匹配的呢?我们可以简单的看看 TextMatcher 的代码,在 TextMatcher 的 matches 方法中充满了诸如清单7中的判断代码。
  清单 7:TextMatcher 的代码片断。& if (w instanceof Button) { &&& setWtext(((Button)w).getText());&&&&&&&& && } && if (w instanceof Combo) { &&& setWtext(((Combo)w).getText());&&&&&&& } &
  这说明所有TextMatcher对于不同的构件会有不同表现,比如 button就是 button的text,combo是选中项的text而tableItem的text则是所有列的text的一个数组。了解这些代码对你构造匹配器有着重要的意义,只有因势利导,你才能更好的使用Abbot。经常会有初学者将NameMatcher和TextMatcher 混淆,如果看看NameMatcher的代码就了解它是匹配构件的类型和变量名,而不是构件的文本。
  细心的读者也许会发现一个问题,Abbot的匹配器过多的依赖于字符串的匹配,这要求最好所有的界面上的文本全部使用常量的方式定义(否则在不同的语言环境中,你的测试用例将寸步难行),这也符合Eclipse国际化的编程要求,可见使用Abbot测试用户界面,会迫使你编写国际化的插件(我们的新建java类测试用例为了简化,就没有做类似的处理)。
  这里有个有趣的话题,我们可以通过使用键盘的快捷键避免使用太多的查找器,菜单的快捷键,Tab键和回车键的组合使用经常能够节省你不少的时间去寻找按钮和菜单,通过WidgetTester.actionKeyPress方法,你可以轻易的模拟键盘事件。同时这也是对你用户界面的Accessibility(易访问性)的极端测试,完全键盘操作是Eclipse界面设计的Accessibility的一项要求。如同我们刚刚提到的国际化的要求一样,这里我们的测试用例反过来能够对代码的质量提出一些强制要求,可见极限编程方法中优先编写测试用例的指导方针果然名不虚传(当然本文提到的国际化和易访问性只是一个无心插柳的副作用,优先编写单元测试代码会强制你的代码简单易读,接口和业务逻辑代码分离,层次清晰,结构明确,并迫使你重构代码,使设计更加细化。有兴趣的读者可以参考《重构,改善既有代码的设计》一书)。
  Abbot 测试代码的同步执行
  Java 语言本身就提供了多线程机制,因为很多的用户界面会通过不同的线程完成不同的任务,有些线程是同步的,有些线程是异步的,你很难保证你测试代码会被同步的执行。SWT要求对UI的操作都要放在新的线程中进行,在我们的JavaWizardTest测试用例中,我们必须使用新的线程去测试界面,同时为了保证测试的同步,我们要等待向导的出现,然后才能执行针对向导的测试代码。读者也许已经注意倒我们的测试用例中openJavaWizard这一方法并未在线程中被调用,那是因为在MenuItemTester中的actionSelectMenuItem操作中,选择菜单的操作已经启动了一个新的线程。
  在我们的等待线程中,我们如果要执行UI构件相关操作的断言,就应当都把他们封装在一个Runnable里面使用“abbot.tester.swt.Robot.syncExec”保证他们被同步的执行,这最终使用到了“org.eclipse.swt.widgets.Dispaly”的syncExec方法。由于SWT单独有一个线程(主线程)处理界面显示,数据显示等,如果要在其他线程中操作界面元素,就必须使用Display的syncExec和asyncExec两个方法执行,即将另外线程的操作交给主线程处理,我们使用的syncExec方法表示要顺序的同步的执行相关的测试操作。对于形如“assertFalse(finishButton.isEnabled())”这样的断言,因为涉及倒了UI构件的操作,就需要包装在syncExec方法内,而形如” assertNotNull(finishButton)”这样的断言,则不需要任何包装,直接在测试线程的代码体内就可以执行。
  研究 Abbot 的源码可以发现,Abbot 的测试器代码中都使用了 syncExec,所以我们唯一需要使用的地方就在执行UI构件相关的断言的地方,但是为了保证代码的统一和完整,我们尽量使用形如如本测试用例的写法。
  在Abbot控制用户界面的测试同时,请不要使用鼠标或者键盘,同时尽量关闭可能会弹出对话框的后台程序,以免使 Abbot 失去用户界面的控制权。不过即使被别的用户界面打断,在有效的等待时间的内,你仍然可以手工帮助界面运行到等待线程的条件处,Abbot会检测到界面并能继续执行下去。如果你在测试 Eclipse RCP 应用,界面的产生可能会和网络条件或者数据量有关系,Abbot默认的等待时间可能不能满足需要。当在默认的时间到达前没有能够等到期望的界面时,Abbot 会抛出 WaitTimedOutError 异常。Abbot 默认的等待时间应该是一分钟,其值在 abbot.tester.swt.Robot 中有定义,见清单 8。
  清单 8. 默认延时的定义protected static int componentDelay =&& Properties.getProperty( "ponent_delay",defaultDelay, 0, 60000);&
  你也可以通过设置延时参数来调整你的测试代码,WidgetTester提供了一些等待方法,其中就可以通过参数来设置延时时间,见图 7。
  图 7:WidgetTester的等待方法&&&&&&&&&&&&&&&&
  如果你有特别的需要,不仅满足于等待对话框或者构件的出现(在RCP应用中常见的就是等待服务器端的返回数据),可以使用abbot.tester.swt.Robot的“wait(Condition condition)”方法。你只要实现自己特定需求的Condition接口就可以让用户界面在等待你期望的结果,如清单9所示,Condition接口相当的简单。
  清单 9:Condition接口的定义public interface Condition {&&& /** Return the condition state. */ &&& boolean test();&&& /** Return a description of what the condition is testing. */ &&& String toString(); }&
  你需要在 test 方法中检查条件,一旦条件满足就返回 true,否则返回 false, Abbot 的 wait 方法会不断去调用 test 方法查询条件是否满足,你在调用时设置超时条件(如 图 7 中的”wait(Condition,long)”方法),如果不设置,Abbot 仍然会使用默认的等待超时值。  循序渐进:编写高效的 Abbot 测试用例
  至此我们已经能够基本掌握 Abbot 的用法,编写简单的测试用例,你也许没有注意到,我们的测试用例是否是有效的测试用例?我们是否可以用更简单的方式,编写更加高效的测试用例?在本文的这一部分,你将能够了解到这些内容。
  使用自定义线程捕获异常
  如果你使用JUnit测试过多线程程序,你会发现JUnit实际上不支持多线程的测试,所有在线程中的断言失败或者异常对该测试用例的结果没有影响。前面我们已经了解到,Abbot的测试通常是使用线程方式进行的,我们还沉浸在一开始就运行成功Java类向导测试用例的喜悦中,也许并没有发现,那并不是一个有效的测试用例。想知道事情的原委,读者可以将JavaWizardTest中findAndTestWizard方法的“assertFalse(finishButton.isEnabled()); ”更改为“assertFalse(!finishButton.isEnabled());”再次运行该用例,你将发现控制台中,JUnit捕获到了junit.framework.AssertionFailedError错误,但是用户界面却停滞不前,当你按下取消按钮帮助界面结束测试,你可以在JUnit视图中发现测试用例居然成功通过。
  此时我们发现两个问题:
  我们在线程中的断言和异常并不能真正的决定测试用例的成败,因此我们的测试用例是无效的。&&&& 在发生异常后,我们并没有考虑到如何使用户界面继续(我们需要手工帮助向导退出),后续的测试方法和测试用例将无法继续进行。&&&& 实际项目中,我们通常使用自定义的测试线程和增加在finally中对用户界面的清理 工作来解决上面两个问题,首先我们定义一个能够简单地显示运行是否成功的线程,请参见清单10。
  清单10:测试线程TestThreadpackage abbottest.
  public class TestThread extends Thread {& private Throwable exp =
  public boolean isSuccess() {&& return (exp == null);& }
  public Throwable getExp() {&&& }
  public void setExp(Throwable exp) {&& this.exp =& } }&
  该测试线程能够记录在运行过程中发现的错误,并提供方法来检查在运行是否成功完成。如果我们将Abbot的测试代码封装在这样的线程中运行,就可以在主线程中判断测试线程运行是否有错误,从而实现测试的目的。
  这样我们经过修改的代码,置于JavaWizardTest2.java,清单 11显示了使用测试线程的JavaWizardTest2的代码。
  清单11:使用测试线程的测试用例package abbottest.import junit.framework.TestC
  import org.eclipse.swt.widgets.Bimport org.eclipse.swt.widgets.Dimport org.eclipse.swt.widgets.MenuIimport org.eclipse.swt.widgets.Timport org.eclipse.swt.widgets.W
  import abbot.finder.matchers.swt.ClassMultiMimport abbot.finder.matchers.swt.TextMimport abbot.finder.matchers.swt.TextMultiMimport abbot.finder.swt.BasicFimport abbot.finder.swt.TestHimport abbot.tester.swt.MenuItemTimport abbot.tester.swt.Rimport abbot.tester.swt.TextTimport abbot.tester.swt.WidgetT
  public class JavaWizardTest2 extends TestCase {& public void testJavaWizard() {&&& final TestThread wizThread = new TestThread() {&&&& public void run() {&&&& WidgetTester.waitForShellShowing("New Java Class");&&&&& try {&&&&& findAndTestWizard();&&&&& } catch (Throwable e) {&&&&&&& e.printStackTrace();&&&&&&& setExp(e);&&&&& }&&&& }&&& };&&& wizThread.start();&&& assertTrue(wizThread.isSuccess());&&& & }
  private void openJavaWizard() {&& MenuItemTester menuItemTester =&&& (MenuItemTester) WidgetTester.getTester(MenuItem.class); && menuItemTester.actionSelectMenuItem( "&File/&New\tAlt+Shift+N/Class",&&& null, Display.getCurrent().getActiveShell(), 1000); & }
  private void findAndTestWizard() throws Throwable{&& TestHierarchy hierarchy = new TestHierarchy(Display.getCurrent());&& final BasicFinder finder = new BasicFinder(hierarchy); && Button cancelButton= && try { &&& final Widget root = finder.find(new TextMatcher( "New Java Class"));&&& final Text nameText = (Text) finder.find(new ClassMultiMatcher(Text.class, 4)); &&& final? Button finishButton=(Button)finder.find(root, &&&& new TextMultiMatcher( "&Finish",1,Button.class));&&& cancelButton=(Button)finder.find(root,new TextMultiMatcher( "Cancel",1,Button.class));& &&& abbot.tester.swt.Robot.syncExec(root.getDisplay(), null, new Runnable() { &&&& public void run() { & &&&&& TextTester textTester = new TextTester(); &&&&&& textTester.actionEnterText(nameText, "classname");&&&& &&&&&& Robot.delay(1000); &&&&& assertFalse(!finishButton.isEnabled()); &&&&&& &&&& } &&& }); && } catch (Exception e) { &&& e.printStackTrace(); && throw(e); && }finally && { &&& WidgetTester.getWidgetTester().actionClick(cancelButton); && } & } }&
  以上代码展示了新的测试线程的用法,并且我们在finnaly中退出该向导,可以保证该测试用例发生错误以后其余的测试用例能够继续运行。同时我们捕获的是Throwable,可以保证捕获到Abbot的异常和JUnit的断言失败。
  至此一切无懈可击,此时你可以运行新的测试用例,等等,为什么运行以后虽然有异常,测试用例看起来还是成功的呢?请在 openJavaWizard();和assertTrue(wizThread.isSuccess());之间 加入清单12中的代码。
  清单12:在测试方法中增加的代码。while (wizThread.isAlive()) {&&&&& WidgetTester.getWidgetTester().actionDelay(100); }&
  再次运行,终于成功通过测试,为什么会这样呢?这是因为测试线程的执行还没有完全完成,但是测试方法中的代码已经走到断言部分了,增加了以上的代码,可以保证在UI线程结束后在继续运行当前的测试方法内的代码,这就能保证测试方法内所有的代码(包括线程内的)都能够同步的被执行,有兴趣的读者可以研究一下Abbot的源码,了解详细的情况。如果你需要在一个测试方法中进行多个在新线程中顺序执行的界面测试行为,这种同步显得尤为重要,你都要使用以上的方法保证这些线程在当前线程的控制之下按顺序的执行,同时需要注意代码的写法,以保证所有的错误能够被当前线程捕捉到,真实地反映到当前的测试用例中。
  基于以上方法,我们可以编写真正高效的测试用例,真正捕获到任何异常和错误,但是我们还有方法使你的测试用例更为简单。  使用 abbot.swt.eclipse 简化你的插件测试
  abbot.swt在abbot的基础上增加了很多SWT的支持,类似的是,Abbot还提供了abbot.swt.eclipse插件为我们的Eclipse插件测试提供了一些便利的功能。abbot.swt.eclipse插件则在abbbot.swt插件的基础上增加了一些实用的测试方法和测试器(图1),极大的方便了对基于SWT的Eclipse插件用户界面的测试。
  图1:新增的测试器
  上图可以看出,abbot.swt.eclipse插件提供了Abbot SWT插件所没有的对话框测试器,能够方便的执行对话框的测试。同时在“utils”包中还提供了很多的实用类,见图2,
  图2,abbot.swt.eclipse的utils包。
  这些类的作用一目了然,的确可以帮助我们方便的进行插件的测试,例如,使用类InvokeNewWizard,我们可以很方便的打开新建Java类向导,只要一行语句就可以实现,见表清单13。
  清单13:使用InvokeNewWizard打开新建Java类向导InvokeNewWizard.invoke("Java/Class", Display.getCurrent().getActiveShell());&
  Abbot 还提供了更好的Abbot TestCase,内置一些测试器以及一些Shell之类Eclipse特有的对象,我们的测试用例可以从“abbot.swt.eclipse.tests.TestCase”派生,可以节省一些工作量。同时在“abbot.swt.eclipse.tests”包中还有很多的测试用例,读者可以学习一下,具有很大的参考价值。
  总体上来说,使用abbot.swt.eclipse插件可以方便的进行Eclipse插件的用户界面测试,这里我们在使用方便之余也能体会到Eclipse插件编程思想中的插件分层思想。分层的思想,对于我们编程序和做项目具有很重要的意义,Eclipse的插件编程,严格的将界面、模型、核心、业务逻辑实用工具等分隔在不同的插件中实现,既能简化插件的开发,又能保证功能的简化。比如Abbot中的三个插件,abbot,abbot.swt,abbot.swt.eclipse,三者之间分工明确,协同工作就能完成Eclipse插件的用户界面测试,也可以单独使用。这里需要说明的是,abbot.swt.eclipse这个插件现在还没有太多的功能,不过我们可以预见,一定会为Eclipse插件的测试提供强大的支持。
  更上层楼:构建复杂的插件测试用例
  目前为止我们已经能够了解到Abbot SWT的全貌,也掌握了Abbot的一些高级用法,现在可以通过一个复杂的测试用例来看看如何在Eclipse环境中使用Abbot开发有效的用户界面测试用例。我们将使用Eclipse自带的一个插件示例作为被测试的插件,我们的测试用例就是要测试该插件的用户界面行为。
  创建示例插件
  我们将使用Eclipse的插件模板创建一个简单的示例插件,首先新建一个名为SampleView的插件项目,在向导的最后一页选择“Plug-in with a view”,点击“Finish”。该示例的目的是供使用者学习视图的编程和相关的操作,观察SampleView.java,我们发现很多的字符串变量,前面提到Abbot的搜索器和匹配器很大程度上依赖于字符串的匹配,为了便于测试,我们需要一定的重构,主要是字符串放到Message中,然后在测试用例中引用,重构后的代码请见附件。此时你可以启动Eclipse的Runtime,打开“Show View” 对话框,如图 3 所示。
  图3:选择“Sample View”&&&&&&&&&&&&&&&&&&&
  选中“Sample Category”下的“Sample View”来打开该插件的视图,点击确认打开Sample View,该视图是一个简单示例,包含一个简单的Table,如图4。
  图4:Sample View&&&&&&&&&&&&&&&&&&
  双击table中的item会弹出对话框,在树节点上选择不同的右键菜也会弹出不同内容的对话框。这个就是这个示例插件的主要逻辑,对于初学者,这是一个很好的学习对象。对于我们,则可以用来作为一个待测试的插件,我们将使用Abbot构建一些端到端的测试用例,来测试该视图的功能。为了测试,你还需要添加给AbbotTest 插件添加新的Dependency,也就是SampleView插件。同时,请在SampleView插件的Runtime设置页中将如图的 2 个包作为导出的包,能够被测试插件引用到,如图5。
  图5;导出sampleview的包
    使用 Abbot 构建复杂的测试用例
  通过对被测试对象的简单分析以后,我们需要创建两个测试方法,分别为测试视图中的双击事件和弹出菜单,同时需要一个方法能够打开视图。我们创建一个名为SampleViewTest的测试用例,详细代码请参考附件中的源码,下面分别介绍该测试用例中三个主要的方法。
  显示视图
  一旦我们运行 JUnit Plug-in Test ,JUnit 会启动一个新的 Eclipse Runtime,我们需要打开待测试的视图,因此清单 14 中的 openSmapleView 方法向我们展示了如何使用 Abbot API 打开一个视图。
  清单14:SampleViewTest的openSmapleView方法protected void openSmapleView()& {
  final Thread showViewThread= new Thread() {&& public void run() {&&& WidgetTester.waitForFrameShowing( "Show View");&&& TestHierarchy hierarchy = new TestHierarchy(Display.getCurrent()); &&& final BasicFinder finder = new BasicFinder(hierarchy);
  try {&&&&& final Widget root = finder.find(new TextMatcher("Show View"));&&&& final Text nameText = (Text) finder.find(new ClassMultiMatcher(Text.class, 1)); &&&& abbot.tester.swt.Robot.syncExec(root.getDisplay(), null, new Runnable() { &&&&& public void run() { &&&&&& TextTester textTester = new TextTester(); &&&&&&& textTester.actionEnterText(nameText, &&&&&&&&&& Messages.SampleView_MSG_DLG_Title); &&&&&&&& Robot.delay(1000); &&&&&& wt.actionKeyPress(SWT.CR,Display.getCurrent()); &&&&&&& Robot.delay(1000); &&&&&& wt.actionKeyPress(SWT.CR,Display.getCurrent()); &&&&&& } &&&& });
  } catch (Exception e) {&&&& e.printStackTrace();&&&& fail(e.getMessage()); &&& } && } & }; & & showViewThread.start();
  wt.actionKey(SWT.ALT+&& SWT.SHIFT+&& (new Integer('q')).intValue(), Display.getCurrent()); & Robot.delay(1000); & wt.actionKey( (new Integer('q')).intValue(), Display.getCurrent());
  Robot.wait( new Condition(){&& public boolean test() {&&& return isSampleViewOpened(); & }}); }
  注意我们用到了上文提到的快捷键的方式来激活显示视图对话框,并使用键盘操作来避免复杂的树操作,注意构件测试器的actionKey方法的用法,通过该方法,你可以方便的进行UI操作,而避免复杂的鼠标操作,对于测试鼠标操作无关的UI,使用快捷键操作可以避免书写冗余和重复的代码。
  试着注释线程内的 delay 语句,你将发现,在树节点还未被选中之前按钮动作就被触发,所以界面无法继续下去。因此在使用Abbot时,我们需要树立一个观念,用户界面的打开或者显示绝对不是一瞬间的事情,我们经常会用等待方法保证用户界面在Abbot的指引下顺利的运行。
  最后的Robot.wait方法向我们展示了自定义等待条件的用法,我们需要调用该方法确定视图已经被打开(因为视图的打开同样需要时间,如果不等视图完全显示就进行下一次操作,可能会导致错误)。在Abbot测试用例中你会经常使用该方法去等待业务操作的完成,实现一个简单的Condition接口就可以做到。
  测试弹出菜单
  使用打开视图方法可以打开示例视图,一旦确认示例视图被打开,我们就可以开始测试,清单15展示了弹出菜单的测试方法。
  清单15:弹出菜单的测试方法。public void testPopupMenu()& { && if(isSampleViewOpened()==false)&&& openSmapleView();&& TestHierarchy hierarchy = new TestHierarchy(Display.getCurrent());&& final BasicFinder finder = new BasicFinder(hierarchy);&& try {&&& final TableItem item =(TableItem)finder.find( &&&& new TextMultiMatcher(Messages.SampleView_One,1,TableItem.class));&&& final Menu m = item.getParent().getMenu();&&& Thread menuClick = new Thread() {&&&&&&&&&&& public void run() {&&&&&&&&&&& item.getDisplay().syncExec(new Runnable() {&&&&&&&&&&& public void run() {&&&&&&&&&&& new Robot().keyPress(KeyEvent.VK_ESCAPE);&&&&&&&&&&& }&&&&&&&&&&& });&&&&&&&&&&& }&&&&&&&&&&& };&&&&&&&&&&& menuClick.start();&&&&&&&&&&& &&&&&&&&&&& // Right mouse click on TreeItem&&& itemTester.actionClick(item, 1, 1, "BUTTON3");&&& &&& MenuItem[] aItems = new MenuTester().getItems(m);&&& &&&&&& Thread actionDialog = new Thread() {&&&&&& public void run() {&&&&&&&&& WidgetTester.waitForFrameShowing("Sample View");&&&&&&&&& try {&&&&&& final Widget root = finder.find(new TextMatcher("Sample View"));&&&&&& Label label=(Label)finder.find(root,&&&&&& new TextMultiMatcher(Messages.SampleView_Action2_executed,&&&&&& 1,Label.class));&&&&&& assertNotNull(label);&&& Robot.delay(1000);&&&&&& wt.actionKeyPress(SWT.CR, root.getDisplay());&&&&&& &&&&&& } catch (Exception e) {&&&&&&&&& e.printStackTrace();&&&&&&&&& fail(e.getMessage());&&&&&& }&&&&&& }&&&&&& };&&&&&& actionDialog.start();&&&&&& &&& itemTester.actionSelectPopupMenuItem(aItems[1], 10, 10);&&&&&& && } catch (Exception e) {&& && e.printStackTrace();&& && && fail(e.getMessage());&& && }&& && && } && private boolean isSampleViewOpened() {&& IWorkbenchPage activePage = && && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();&& if (activePage.getActivePart() instanceof SampleView)&&&&&& }&&
  这里我们使用到了激活鼠标右键的操作:itemTester.actionClick(item, 1, 1, "BUTTON3"),该句语句中"BUTTON3"表示右键,这条语句能够执行右键单击的操作,从而显示右键菜单,类似的操作我们在Abbot的测试中会经常使用到。这里有个奇怪的menuClick线程,该线程的作用是点击键盘上的退出键,读者可以尝试注释该线程的代码,运行测试,观察用户界面的显示,你可以发现界面被阻塞在右键菜单处,无法选中菜单。在显示菜单后,执行menuClick线程就可以避免这种情况的出现。
  读者也可以看见,我们会通过root参数缩小查找范围,这里的root就是弹出对话框的Shell。在“wt.actionKeyPress(SWT.CR, root.getDisplay());”语句中你同样需要使用该shell对象,该语句的意思是在弹出的对话框中按下回车键,显然比找到OK按钮,然后点击OK按钮要方便的多。同时因为测试线程只是进行了简单的判空操作,并没有直接执行UI构件的操作,所以我们不需要在使用Robot.syncExec方法执行测试代码,而是将其直接置于线程体内即可。在编写具体的测试用例的时候,我们应当尽量以简单易懂为原则,灵活的使用Abbot API,编写出简洁高效的测试用例。
  测试双击事件
  测试完右键菜单后,我们再看看如何测试表中的Item的鼠标双击事件,参见清单16的代码。
  清单16:测试鼠标双击的方法&& public void testDoubleClick()&& {&& if(isSampleViewOpened()==false)&& && openSmapleView();&& TestHierarchy hierarchy = new TestHierarchy(Display.getCurrent());&& final? BasicFinder finder = new BasicFinder(hierarchy);&& && Thread actionDialog = new Thread() {&& && public void run() {&& && && && try {&& && && && && final TableItem item =(TableItem)finder.find( && && new TextMultiMatcher(Messages.SampleView_One,1,TableItem.class));&& && && assertNotNull(item);&& && && wt.actionClick(item, 6, 3, "BUTTON1", 2);&& && && && && && WidgetTester.waitForShellShowing(Messages.SampleView_MSG_DLG_Title,2000);&& && && && && && && && && && final Widget root = finder.find(&& && && new TextMatcher(Messages.SampleView_MSG_DLG_Title));&& && Label label=(Label)finder.find(new TextMultiMatcher(&& && && && NLS.bind(Messages.SampleView_Double_click,&& && && Messages.SampleView_One),1,Label.class));&& && assertNotNull(label);&& && Robot.delay(1000);&& && wt.actionKeyPress(SWT.CR, root.getDisplay());&& && && && && } catch (Exception e) {????????? ?? e.printStackTrace();&& && && && fail(e.getMessage());&& && && && }&& && }&& };&& actionDialog.start();&& //??safe join&& while (actionDialog.isAlive()) {&& wt.actionDelay(100);&& }&& & }&
  双击事件的测试再次向我们展示了鼠标事件的用法,通过“wt.actionClick(item, 1, 1, "BUTTON1", 2)”这行代码,我们可以单击鼠标左键两次,注意如果不加以控制,这两次的点击会引起线程相关的问题,所以我们使用上文论述过的方法来控制代码能够同步执行。也就是我们首先启动测试线程,然后使用while方法等待,测试线程不执行完毕,当前线程就一直等待,这样可以保证的测试线程内的测试动作完全执行完成后再将控制权返回当前线程,继续运行。
  本部分的代码展示一个复杂的测试用例中怎样进行一些复杂的测试,完整的测试代码请参见附件。读者也许已经意识到,编写复杂的Abbot测试用例会强迫测试人员对SWT用户界面的运行原理、事件、线程等机制有比较深入的了解,这也从另外一个方面促使你更加深刻的掌握SWT的用户界面编程。因此测试用例对我们的影响是多方面的,除了上文论及的国际化和易访问性,也会对我们的知识的深度进行一次洗礼,使你对被测试的代码和背后的运行原理,有更为深刻的认识。
  至此,我们已经能够了解 Abbot 的基本概念和原理,并能理解和执行一些测试用例。我们可以看出 Abbot 整个的逻辑非常的简单,无非是找到一些待测试的构件,执行相关的动作,比较测试的结果。如果组合使用这些简单的逻辑,就能够测试很复杂的界面。对于用户定制的特定的UI,比如使用 gc 直接绘制的构件,或者是一些特定的复合构件可能需要对 Abbot 做相应的扩展,你也可以分析 Abbot 的源代码,扩展相应的测试器来解决这些问题。在 Abbot 的测试中尤其需要注意线程同步的问题,文中我们很多地方都有讨论,读者在自己编写测试用例的时候需要注意。虽然编写端到端的用户界面测试用例比较麻烦,但是熟悉以后,你可以很快的写出高效的测试用例,显著提高你的开发和测试效率。
  本文并没有讨论到Abbot的脚本和Swing的Abbot测试。各种各样的脚本在我们的编程中总是起着事半功倍的效果,通常我们使用的各种测试工具都会有脚本的概念,Abbot 也不例外。Abbot使用可以简单的xml文件记录测试过程,并提供了脚本编辑器来编辑和运行,有兴趣的读者可以从Abbot站点获取相关的资料。关于AWT和Swing的测试,Abbot的网站上提供了足够的示例,如果需要的读者可以访问Abbot站点。
  从实用的角度来说Abbot插件的功能已经足够应付一般的Swing和SWT的测试,不过其针对Eclipse插件的测试相关的功能还在开发过程中,我们希望尽快能够有发布的版本,能够更全面的支持Eclipse插件的测试。
  就像你为所有重要的功能编写了单元测试一样,我们建议你为重要的界面编写测试用例,尤其对于一些数据敏感的动态生成的用户界面,Abbot的测试非常重要。但是,我们不推荐像写单元测试一样写细粒度的用户界面测试,自动化的工具不能完全代替人去执行手工的测试。即使我们有100%覆盖的用户界面测试用例,也不能完全保证用户界面适用于真正的用户,何况,编写100%覆盖的用户界面测试用例是不可能的,UI的外观,易用性,单词的拼写错误,构件的对齐等很多问题,只能由人去测试。
  但是Abbot等自动化测试工具的意义仍然非常重要,如同我们展示的一样,对于重复的界面测试,数据或者业务逻辑紧密联系的界面,界面的流程和操作等,使用工具或者脚本能够极大的减少测试人员的工作量。实际项目中,我们更倾向于通过UI的动作来测试业务逻辑,通过端到端的测试用例来实现功能的测试,除了自动化程度高以外,还可以避免代码的改变和业务逻辑的改变带来的测试用例的改变。对于一个设计良好的Eclipse插件,UI的变化频率应该远远的低于业务逻辑的变化(在某种的意义上),因此通过界面去测试业务逻辑是很好的一种选择。选择重要的流程,通过Abbot构建端到端的测试用例,能够覆盖到绝大多数的业务流程,这样的测试经过我们实践的证明是有效的。
&&&主编推荐
&&&热门试卷
&&&最新视频
&&&热门阅读
&&&最新问答
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&增值电信业务经营许可证湘B2-}

我要回帖

更多关于 qtp自动化测试实践 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信