一种基于 SWTBot 的 GUI 自动化测试框架

简介: 本文基于笔者在实际项目中使用 SWTBot 的最佳实践,介绍如何构建和使用基于 SWTBot 的 GUI 自动化测试框架。本框架遵循结构分离,代码重用的原则进行设计,把 SWTBot 的原子操作进行封装,提供通用的 API。在此基础上,脚本开发者可以对特定产品的组件和基本操作进行定义,从而可以简单快速的开发出高质量的 GUI 测试脚本。


背景简介

SWTBot 是一个基于 Java 的新兴开源项目,致力于实现对基于 SWT 和 Eclipse 的应用程序 GUI 的自动化测试。当前,基于 eclipse 和 SWT 的产品非常多,随之而来的对于这一类产品的自动化测试需求也就越来越多。SWTBot 本身是一种轻量级,易用的工具,能够很好的实现对于 SWT 和 Eclipse 产品的自动化测试。但是由于 SWTBot 目前尚处于孵化阶段,对于如何将其成功应用到实际项目当中论述很少。

当前来说,对于基于 SWT 和 Eclipse 的应用程序的用户交互界面进行自动化测试通常是复杂繁琐的。本文介绍一种基于 SWTBot 的测试框架能够很好的帮助开发人员和测试人员实现 GUI 的自动化测试。

体系结构

一个定义良好的测试框架可以大大提高测试用例开发人员的工作效率。本文要介绍的测试框架基于 SWTBot,以结构分层,代码重用,维护简单,扩展简便为原则,对其功能进行封装和扩展,使其易于理解和使用。框架通过简单的维护就能适应测试产品的变化。

对于 GUI 测试来说,我们会把一些基本的操作放在最底层。例如:对原子操作进行封装,测试框架工具类,以及一些对通用控件的封装。

在此之上的第二层,我们会把测试用例当中使用到的所有组件进行封装。这些组件包括一切编写测试用例需要用到的对象,例如对话框 (Dialog),编辑器 (Editor)。在此基础上,给出针对这些对象的一些接口,例如 setText(),click(),或者给出得到这些对象实例的方法。

我们知道,GUI 上有大量的文字信息,像对话框的标题,按钮的名称。我们也可以把这些信息放在下一层 ( 测试用例层 ) 中处理,但是其缺点是显而易见的。首先,这些文字信息的数量很多,如果全都写在测试用例中,代码会显得异常混乱。其次,如果这些信息发生了变化(这种可能性是很大的),在测试用例数量很大的情况下,想找到这些信息再一一进行修改是一件极其困难的事情。在我们的测试框架中,这些文字信息被放在配置文件中进行统一管理,一个控件对象对应自己的配置文件,在封装这些控件对象的同时对其包含的文字信息进行封装并提供相应的方法。这样的处理避免了上面提到的问题,很好的杜绝了下层代码对上层测试用例的影响,实现了代码分离。

编写测试用例的工作在最上层完成。在这一层当中,测试用例开发者的工作变得相当简单。他们通过调用第一、第二层封装对象提供的方法和接口来实现测试步骤。

综上所述,我们的测试框架的体系结构如下:


图 1. 测试框架体系结构
图 1. 测试框架体系结构

在下面的几章,我会详细介绍本框架的结构和具体实现。

工具层 , 封装 SWTBot 的原子操作

我们框架的基础是 SWTBot 提供的对 SWT 和 Eclipse 的操作功能。所以,本框架的最底层就是对 SWTBot 原子操作的封装以及其他一些工具类。


图 2. 工具层基本结构
图 2. 工具层基本结构
  • com.ibm.developerworks.dbconnect: 提供数据库连接的管理和通用方法。
  • com.ibm.developerworks.eclipse:提供对通用的 Eclipse 组件的封装和相应方法。
  • com.ibm.developerworks.finders:对 SWTBot 进行扩展,提供一些针对相应产品,易于使用的 finder。
  • com.ibm.developerworks.matchers:提供编写测试用例时需要用到的匹配方法,例如正则表达式匹配,通过 label 或者 text 等条件匹配。
  • com.ibm.developerworks.utils:封装各种 SWT 控件对象的操作,例如 Mouse,Menu,TableItem 等。
  • com.ibm.developerworks.waits:对 SWTBot 自有的 Conditions 进行封装和扩展,提供一些针对特定产品的 wait 方法。
  • com.ibm.developerworks.widgets:封装一些公用的 widget。

举一个具体的例子来说明,我们在 waits 包里提供 waitForShellClosed,代码如下:


清单 1. 等待 shell 关闭
				
 /** 
 * Wait for shell closed 
 * 
 */ 
 public class WaitForShellClosed extends DefaultCondition { 
   Matcher<Shell> matcher; 
   Shell parent; 
   public WaitForShellClosed(Matcher<Shell> matcher){ 
     this(matcher, null); 
   } 
   public WaitForShellClosed(Matcher<Shell> matcher, Shell parent){ 
     this.matcher = matcher; 
     this.parent = parent; 
   } 
   @Override 
   public String getFailureMessage() { 
     return "Found shell "+matcher; 
   } 
   /** 
   * test the shell exists 
   * @return true if not exist, false if exists 
   */ 
   @Override 
   public boolean test() throws Exception { 
     int count = 0; 
     Shell[] shells = null; 
     if( parent != null) 
       shells = parent.getShells(); 
     else
       shells = bot.getFinder().getShells(); 
     for (Shell shell : shells) { 
       if (matcher.matches(shell)) { 
         count ++; 
       } 
     } 
     return !(count > 0); 
   } 
 } 

组件层,封装测试对象的组件和公用任务

控件层对所测试产品的控件进行封装,提供给下一层的测试用例开发者使用。在这一层当中,主要封装所有的对话框或其他窗口对象,以及这些对象上控件的操作方法。主要调用工具层的基本控件方法来实现。


图 3. 组件层基本结构
图 3. 组件层基本结构

从包名当中能很清楚的看出每个包的作用,在此就挑选两个典型的包来介绍,其他就不再一一介绍了。以 com.ibm.developerworks.dialogs 和 com.ibm.developerworks.constants 为例。顾名思义,开发人员对测试当中用到的所有 dialog 进行封装,放在 dialogs 包中;constants 包则保存每个对象当中的所有文字信息。看下面的例子:


清单 2. 对话框的封装
				
				public class ExportWorkloadDialog extends BaseDialog { 
   public static final String messageFile= 
        "com.ibm.developerworks.constants.ExportWorkloadDialog"; 
   protected ExportWorkloadDialog() { 
     super (UIConstants.getConstant(messageFile, "TitleName_dialog")); 
   } 
   public static ExportWorkloadDialog getInstance() { 
     return new ExportWorkloadDialog(); 
   } 
   public SWTBotText textWithLabel_file() { 
     return shell().bot().textWithLabel( 
         UIConstants.getConstant(messageFile, "textWithLabel_file")); 
   } 
   public SWTBotButton button_browse() { 
     return shell().bot().button( 
         UIConstants.getConstant(messageFile, "button_browse")); 
   } 
   public SWTBotRadio radiobutton_workloadDefinitionOnly() { 
     return shell().bot().radio( 
         UIConstants.getConstant(messageFile, 
            "radiobutton_workloadDefinitionOnly")); 
   } 
 } 


图 4. 对话框封装的结构
图 4. 对话框封装的结构

这个类封装了名称为 ExportWorkload 的对话框。它包含了对这个对话框里所有的控件的封装,并提供方法供测试用例调用。如果测试用例中需要点击 browse 按钮 (Button),那么相应的代码可以写成这样:


清单 3. 测试用例代码示例:点击 browse 按钮
				
 ExportWorkloadDialog dialog=ExportWorkloadDialog.getInstance(); 
 dialog.button_browse().click(); 

从上面的代码片段来看,测试用例中完全不用把按钮的名称写死在代码当中。 如果这个按钮的名称改变了,测试用例也不用做任何改变。这种处理的好处是显而易见的,测试用例的维护成本大大降低了。

那么这些文字信息又是怎么处理的呢?我们把所有的文字信息进行集中管理,这里就要说到 constants 包了。这个包里存放的都是与已封装对象同名的 property 文件。与 ExportWorkloadDialog.java 对应的就是 ExportWorkloadDialog.properties。


图 5. Property 文件示例
图 5. Property 文件示例

Property 文件以键值对的形式 (Key=Value) 保存组件对象中的文字信息。那么对一个特定文字信息的引用就只需要知道其对应的键名就可以了。类似的,如果产品中某个文字信息有了改动,我们可以很容易的找到它,而且只需要对一个地方修改。在这个例子中,对 ExportWorkloadDialog 及其包含的控件进行封装时就用到了这种方法,看下面的代码:


清单 4. 配置信息的使用示例
				
				public static final String messageFile= 
         "com.ibm.developerworks.constants.ExportWorkloadDialog"; 
 public SWTBotButton button_browse() { 
     return shell().bot().button( 
         UIConstants.getConstant(messageFile, "button_browse")); 
 } 

变量 messageFile 定义了文字信息所存放的位置,也就是存放在 com.ibm.developerworks.constants 包的 ExportWorkloadDialog.properties 文件中。所以,在 button_browse() 方法中通过名称定位 browse 按钮时,就通过 UIConstants.getConstant(messageFile, “button_browse”) 来查找 property 文件中 button_browse 对应的键值“Browse …”,从而最终定位这个按钮。

测试用例层,快速开发易维护的测试脚本

测试用例层是开发并保存测试脚本的地方。通过调用组件层封装的对象和方法来实现测试功能,包括执行操作、断言等。进过工具层和组件层的准备,在这一层中开发测试用例就是一件很快速的事情了。同时,这种清晰的结构划分也保证了开发人员写出的测试脚本是逻辑清晰,易于维护的。SWTBot 的测试用例时基于 Junit 的。所以测试用例的结构和 Junit 一致,在此不再赘述。

测试结果的分析和管理

GUI 自动化测试中,导致测试用例失败的原因通常为找不到对象或者断言错误。所以测试用例除了要生成详细的日志 (Log) 之外,测试用例失败时的截屏 (Screen_Shot) 也是非常有价值的。通过截屏,熟悉产品的人可以很容易的找出出错的原因。


图 6. 截屏报告示例
图 6. 截屏报告示例

另外,通过 Junit 我们为每个 Test Suite 产生一份测试报告,最后汇总为一次测试的综合报告。

小结

GUI 的自动化测试一直是费力且困难的工作。但是如果实现了自动化测试,对于人力成本和时间的节省也是巨大的。

SWTBot 是功能强大的 GUI 自动化测试工具。我们扩展了它的强大功能,并定义了结构清晰,分工明确,易于扩展的测试框架。通过这个基于 SWTBot 的 GUI 自动化测试框架,测试人员可以快速高效的开发出高质量的测试用例。希望本文的描述能给大家启发,起到抛砖引玉的作用。


参考资料

学习

讨论

欢迎加入 My developerWorks 中文社区

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值