(原创)使用类和xUnit模式实现GUI测试代码

上一篇 / 下一篇  2010-09-21 12:53:57 / 个人分类:测试框架

 

简述

本文采用类对象的方式封装了项目的主要窗口的GUI对象,大大方便了项目的主要窗口对象的调用和扩展。同时,也封装了GUI对象的检查点方法,使得测试代码逻辑进一步得到简化。另外,借鉴了xUnit模式的设计方法,TestCaseTestSuit进行了分离,方便了后续对测试代码的维护.

动化测试的核心问题就是如何减少维护量,例如:我们应该使用对象库还是描述性编程?如果选择OR那么我们可以在每个ACTION中使用共享对象库或者本地对象库,那如果选择DP,可以有什么方式来实现吗?

成本效益和可维护性是我们在做自动化测试中最为关注的,在此引出一个概念-GUI层扩展。这一概念经过的SOLMAR自动化专家组的分析和观察已被采纳,使用它就可以尽可能地提高代码重用性(通过使用面向对象的方法来提高效率,并分解出若干个抽象层且可维护性较高的自动化项目)。

本文的思路是来源于QTP自动化测试的著名Web站点Advance QTPMeir Bar-Tal的一篇文章<<Implementing a GUI Layer with Classes>>.这篇文章介绍了一种基于QTP的为为先进的自动化测试技术,本技术是由AdvancedQTP SOLMAR自动化测试专家组采纳的一组面向对象的实现技术中的一种。这种技术主要是把QTP描述性编程以及装载GUI对象的DICTIONARY对象通过业务驱动的方式来得到体现,最有价值的地方在于其对象识别的先发机制,可以有效的防止QTP在运行时识别对象出现卡住的现象,当对象出现不匹配时,能使测试顺利退出,并在报告中定位细节。有效的降低了测试的维护量并节省了自动化测试的时间。

 

一.          GUI

1.       封装GUI对象

下面使用项目CCConfirmDialogClass窗口封装的GUI类做一个简单的介绍. CCConfirmDialogClass分为四个主要的部分:

1)     对象类属性存取方法

CCConfirmDialogClass内置一个Scripting.Dictionary类型的m_htChildObjects成员,它主要是用来存储GUI对象集合。

 

2)     测试对象GUI界面控件对象层

在类对象初始化中利用Scripting.Dictionary容器对象,把GUI控件对象层上的对象封装起来,直接通过关键字在字典对象中定位对象,并针对对象进行操作来达成关键字字典对象驱动。

 

3)     测试对象初始化检查公共函数

类对象在运行时需要很多公共行为的函数,比如IsInitialized函数判别GUI对象是否已经被正确的被加载,防止测试对象发生变化以后,与对象库中的对象无法匹配时测试流程会被中断导致超时错误信息,这样的情况会导致在自动化测试中浪费无谓的时间,因此使用工具函数IsContextLoaded函数检查GUI层中所有对象的是否已经存在并且把结果进行返回。其实这个函数的使用的时候并不是这么理想,有部分对象也在这个GUI层里但是并不是可见的,用这个方法只能检查始终是可见的对象,因此,稍后会讨论对于这种情况的解决方法。

 

4)     业务逻辑函数

CCConfirmDialog的主要业务逻辑行为就是对将要执行的行为回答”YES”或是“NO”。业务行为函数封装了采用关键字对测试对象访问的方法,提供了方法调用的易用性和可维护性。

代码示例如下图所示:

 


2.       使用GUI对象

GUI对象的实例采用了对象工厂方法实例化一个全局变量,供调用的其他GUI类或者测试逻辑中使用。

 

GUI对象实例调用的形式如下图所示:

CCClassFactory方法有三个参数:

·       strClassType:需要创建的GUI类名

·       objObject:对象实例变量

·       byval strObjec:对象实例变量名称

 

CCClassFactory方法使用类单例模式(Singleton Pattern)实现,避免了GUI对象实例被多次引用时对象重复创建。

 

3.       封装复杂GUI对象

项目中有一些GUI对象较为复杂,比如一个GUI对象里包含多个子GUI对象,比如项目的Destination Profile Configuration窗口:


 

因此,将Destination Profile ConfigurationGUI类分解为三个GUI子类:

由此就可以分别将GUI对象和对于的业务逻辑封装在不同的子类中,而公共的GUI对象,比如Turn Edit On对象就封装在Destination Profile Configuration窗口GUI类中,这样很好的提升了代码的复用性。

4.       简化测试执行流程

通过GUI对象的封装,对测试执行流程进行了有效的简化,并且对代码的可读性也有了显著的改善。下面是一个Add Destination Profile测试的例子。

 

二.          检查点类

既然通过对GUI对象的封装可以简化了测试执行的流程,能不能将这种方法推广到测试检查流程呢?检查点的流程和测试执行流程既有关联由于区别,通常情况下需要重复部分测试流程,但是也有不同的附加流程,比如在Patient Input的检查流程需要对已经录入的Patient记录进行检索,然后再查看录入的内容,因此使用对GUI对象的封装方法,也对检查点对象使用的GUI对象和检查逻辑进行封装。下面是一个检查Add Destination Profile的例子:

由此简化的测试执行流程和检查流程如下图所示:

 

三.          使用xUnit Pattern重构测试代码

1.       断言(Assert

断言是xUnit的最大特色之一,简化的调用方式使得嵌入在代码逻辑内的检查点既简洁又明确当前的检查类型和目标。封装一个Assert Class能够很好的简化测试流程,而且可以重构一些不明确的测试检查点。

Assert Class提供一些检查方法,比如assertEquals(检查两个变量相等),assertTrue(检查变量是否为真)等。

虽然我们模仿了xUnit的断言,但是也不能一味的照搬,事实上与白盒测试不同的是基于GUI测试的检查点不仅仅需要检查结果,还需要通过检查控制测试流程是否进行下去,比如某个窗口不存在时就需要报错,然后中断测试流程执行下一个测试。xUnit的断言不是基于GUI的并不需要考虑这个问题。因此,必须对测试检查点进行分类实现。从检查以后产生的执行结果,我将检查点分为控制点(Control Point)和观察点(Observation Point)。观察点控制点只做值的检查,在检查成功或失败以后输出相应日志;控制点值的检查,在检查失败以后输出失败的日志,并且终止程序的执行。当然,这种划分不是绝对的,在有需要的情况下可以进一步扩展不同的检查点类型。

由此,assertEqualsassertTrue分类为两组检查点方法:assertCPEqualsassertCPTrueassertOPEqualsassertOPTrue

采用断言方法,测试的执行和检查可以进一步的被重构:

 

在使用VBScript实现断言过程中,由于VBScript并不提供支持try-catch的异常抛出和捕捉处理机制。但是通过VBScript提供的on error resume nexton error goto 0机制来实现断言机制。实现的大致过程如下:

2.       SetUpTearDown

使用SetUpTearDown方法可以将测试的前置条件(Prerequisite后置条件(Restoration)进行有效的封装,重构以后的测试代码显的更加有条理和边界分明。比如,使用指定的用户登录系统是一个常见的前置条件。

3.       TestSuite

对于一组测试用例采用TestSuite的方式进行组织。与TestCaseSetUpTearDown方法类似,也可以采用同样的方法将更高层的公共前置条件和后置条件进行重构。下面是一个简单的例子:

 

 

 

四.          结束语

通过此次实践,我们找到了一种提高测试代码复用性的方法,虽然使用的效果还不是最为理想的,但是随着宿主语言对OO的支持的改进,这种思想和方面必将成为自动化测试发展的方向。


TAG:

 

评分:0

我来说两句

Open Toolbar