尘世中一迷途小书童,快乐开发,快乐测试

发布新日志

  • MQC简介

    2009-03-06 00:23:40

    Quality Center(简称QC) 是美国Mercury Interactive公司推出的基于 Web 的测试管理工具,包括对测试需求、测试计划和测试案例、测试执行、软件缺陷等的集中管理。 应用程序测试是一个复杂的过程,涉及到成千上万个测试的开发与执行。对于多种硬件平台、多种配置(计算机、操作系统和浏览器)以及多种应用程序版本,通常都需要进行测试。管理测试流程的方方面面很浪费时间,而且难度也很大。 QC有助于维护测试的项目数据库,这个数据库涵盖了应用程序功能的各个方面。QC供了一种直观、高效的方法,用于计划和执行测试集、收集测试结果以及分析相关数据。 QC具有一套完善的系统,用于跟踪应用程序缺陷,通过它,您可以在从初期检测到最后解决的整个过程中严密监视缺陷。将 Quality Center 链接到电子邮件系统,所有应用程序开发、质量保证、客户支持和信息系统人员可以共享缺陷跟踪信息。 QC可以集成 Mercury 测试工具WinRunner、QuickTest Professional、QuickTest Professional for MySAP.com Windows Client、LoadRunner 和 Visual API-XP)以及第三方和自定义测试工具、需求和配置管理工具。QC可以无缝地与这些测试工具通信,提供一种完整的解决方案,使应用程序测试完全自动化。 QC可指导我们完成测试流程的需求指定、测试计划、测试执行和缺陷跟踪各个阶段。它把应用程序测试中所涉及的全部任务集成起来,有助于确保客户能够得到最高质量的应用程序。
  • 简介RFT实现 ITCL (或者IBM) 框架

    2008-06-02 17:58:50

    为了使应用程序的功能测试自动化,这篇文章介绍了一个使用 Rational Functional Tester 实现ITCL框架的五步过程。

    介绍

    很多论坛和团体都对IBM框架(或者ITCL框架)进行了详细的说明:它究竟是什么,它怎样工作以及它有什么潜在的优势。这篇文章的目的就是集中讨论IBM框架的实现。它将详细说明了为了自动化应用程序的功能测试,通过利用 IBM® Rational ®Functional Tester,IBM 框架是如何被实现的。







    框架

    IBM 框架以前被称作为 ITCL 框架,由质量软件工程(Quality Software Engineering) 和 IBM 中有经验的自动化团队合作开发而成的。这个框架由三层架构组成,架构的实现贯穿了应用对象、任务和测试用例包(IBM 包)。

    潜在于应用对象、任务和测试用例包之下的基本原理是:

    • 层次化的体系架构
    • 将“做什么”与“如何做”分离开来
    • 代码重用
    • 一致和清晰的组织结构
    • 快速增强的能力
    • 迅速的调试
    • 有效地组织文件
    • 启用协作
    • 学习他人

    下面是对应用对象、任务和测试用例的解释说明:

    • 应用对象:储存有关你的应用程序中的GUI元素信息。同时在这里也可以编写你的Getter 方法,这些 Getter 方法可以返回对象,使 调用者能够对这些GUI元素进行查询和操作。一般情况下,这些方法在Task层中进行调用。
    • 任务:在这里你将编写可重用的方法,这些方法在你的应用程序中执行通用功能。同时在这里,你将编写可以处理和查询复杂的特定应用程序控件的方法。在任务中的方法可以被测试用例调用。
    • 测试用例:导航一个应用程序,验证其状态,并记录其结果的方法。





    实施方法论

    在本章节中概述的方法论详细说明了实施IBM框架的5个步骤。

    步骤1. 首先,在你的本地驱动器上创建一个新的项目。这个项目中有一个你可以储存、维护、编译和运行你的自动化代码的储存库。在Functional Tester中,选择File > New > Functional Test Project。给这个项目命名,并点击Finish

    步骤2. 将 IBM 的包― 它包括将在自动化脚本中广泛使用的工具类 ― 导入到你的项目中。尽管这可能只是简单地将路径关联到ibm.jar文件,但是将 IBM 的包导入到你的项目中就可以使你更容易地检查这个包的内容,然后在调试的时候进入到包中。这个IBM的包可以在这篇文章末尾的下载部分中进行下载。

    导入 ibm.jar 包

    1. 在 IBM Rational Functional Tester中,进入屏幕左边的Projects视窗,点击在步骤1中创建的项目
    2. 选择 File > Import。选择 Zip file 然后点击Next。使用Browse按钮在你储存这个文件的指定位置上查找ibm.jar 或者ibm.zip 文件。
    3. 保留所有默认设置并点击 Finish
    4. 你现在应该可以在Functional Test Projects视窗中扩展你项目的名称。你可以在它下面看到一个名为ibm的文件夹。

    步骤3. 创建一个名为AppObject的包

    1. 在IBM Rational Functional Tester中,进入屏幕左边的Projects视窗,在步骤1中创建的项目上点击。
    2. 选择File > New > New Test Folder
    3. 给文件夹命名为AppObject
    4. 点击Finish
    5. 重复1-4的步骤,创建TasksTestCase 文件夹

    什么是 AppObject 包?

    在这个包中你必须映射所有被测试应用的对象。一个最常见的建议是为每一个屏幕准备单独的脚本,以此确保更好的对象以及分类的的重用和组织。比如,创建一个名为login的脚本,它将使所有的对象跟login 界面保持相关。你同样可以创建其它与 sentinbox 界面等等相关的脚本。

    使用 AppObject 文件夹进行工作

    1. 在 AppObject 包中建立一个空脚本
    2. 选择 AppObject 包,点击右键并选择 Add Empty scrīpt,如图1所示。

    图1. 添加一个空脚本
    添加一个空脚本
    1. 将其命名为Login,并点击Finish
    2. 从脚本资源管理器中双击Private Object Map
    3. 确保 mail.yahoo.com site 网站(或者被测试应用)是打开的。
    4. 从 Private Object 图中,点击Test Object > Insert Object(s),如图2所示。

    图2. 插入一个测试对象
    插入一个测试对象
    1. 将指针图标工具从下面的对话框拖到你想映射的目标位置,如图3和图4所示。

    图3. 通过拖拽选择一个对象
    通过拖拽选择一个对象

    图4. 选择的对象
    选择的对象
    1. 点击Finish
    2. 你的Private Object Map窗口应该看起来如图5所示。

    图5. 已完成的 Private Object Map
    已完成的 Private Object Map
    1. 选择你最近添加的对象,点击右键并选择 Add to scrīpt AppObject.Login
    2. 对所有你想要添加到这个脚本的对象重复6-10的步骤。
    3. 点击File > Save并关闭它。你的脚本资源管理器应该看起来如图6所示。

    图6. Login的脚本资源管理器
    Login 的脚本资源管理器
    1. 类似地,你可以尽可能创建更多的脚本到你的项目中,并添加相关的对象。

    自动产生 AppObjects 代码

    一旦你将你的对象添加到你的对象地图中,就可以通过编写几行代码自动产生你的getter 方法。这些getter 方法将帮助你访问跨越或在项目中被添加的脚本中的对象。你将在AppObject文件夹中创建一个空的脚本,编写如列表1中所示的代码来自动产生getter方法

    1. 在AppObject文件夹中创建一个名叫getter 的空脚本文件。
    2. 创建列表1中的代码。

    列表1.自动生getter的代码
                    
    //IMPORT THESE 2 STATEMENTS AT THE TOP OF scrīpt
    import java.util.Vector; 
    import ibm.tools.ClassGenerator;
    //WRITE DOWN  THE BELOW CODE IN TESTMAIN FUNCTION
    public void testMain(Object[] args) 
    	{
    		Vector v = new Vector();
    		v.addElement (new AppObject.Login ());
    	//ADD ELEMENT FOR ALL THE scrīptS YOU HAVE IN YOUR AppObject
    		new ClassGenerator().updatescrīpts(v);
    	}				
    				

    1. 你的Getter脚本内容看起来应该如图7所示。

    图7. Getter 脚本
    Getter 脚本
    1. 选择scrīpt > Run来运行这个脚本。
    2. 运行一次以后,当你点击你的Login脚本时,它将查询你是否要装载这些变更。
    3. 点击Yes,你应该可以看到你的Login脚本已经有了Getter功能,如图8所示。

    图8. 用 Getter 脚本登陆系统的功能
    用 Getter 脚本登陆系统的功能

    步骤4. 创建任务

    任务是你可以编写最大限度重用和最复杂代码的位置。

    1. 首先在Tasks文件夹中创建一个脚本(跟前面的AppObject Folder操作一样)
    2. 选择Tasks文件夹,右键点击它并选择Add Empty scrīpt
    3. 指定详细的名称并点击Finish
    4. 将列表2中的代码插入到脚本中。

    列表2. 登陆任务
                    
    //DECLARE THE OBJECT OF THE scrīptS EXIST IN APPOBJECT 
    public AppObject.Login lgn = new AppObject.Login();
    ….
    ….
    public AppObject.Login lgn = new AppObject.Login();
    	public void AssignLoginInfo()
    	{
    		lgn.getText_login().setText("abc");
    		lgn.getText_passwd().setText("New1");
    	}
    
    public void testMain(Object[] args) 
    {
    }							
    				

    1. 你的脚本内容应当看起来如图9所示。

    图9. 修正脚本内容
    修正脚本内容
    1. 你可以在同一个脚本或者新的脚本中根据每个应用程序的需要随意增加各种功能。

    接下来,你将使这些功能实现自动化

    步骤5. 创建测试用例

    在测试用例中,你可以编写现有的步骤来完成这些行为,这将继承一些 Tasks 和 Appobject的属性特征。

    1. 首先在Tasks文件夹中创建一个脚本(跟前面的AppObject Folder操作一样)
    2. 选择Tasks文件夹,右键点击它并选择Add Empty scrīpt
    3. 指定详细的名称并点击Finish
    4. 将列表3中的代码插入到脚本中。

    列表3. 测试用例
                    
    //DECLARE THE OBJECT OF THE scrīptS EXIST IN TASKS 
    //OBJECT CREATION OF TASKS LOGINTASK scrīpt
    	public Tasks.LoginTask lt = new Tasks.LoginTask();
    ….
    ….
    public void testMain(Object[] args) 
    {
    	//INVOKING THE BROWSER
    	startBrowser("mail.yahoo.com");
    	//ASSIGNED THE USER NAME AND LOGIN INFO
    	lt.AssignLoginInfo();
    	//CLICKED ON LOGIN/SUBMIT BUTTON
    	lt.lgn.getButton_signInsubmit().click();
    	//FURTHER ACTION CAN BE WRITTEN ACCORDIUNLGY		
    }
    

    1. 你的脚本内容看起来应当如图10所示

    图10. 最后的脚本
    最后的脚本
    1. 现在运行这个脚本,打开浏览器,输入用户名和密码,然后登陆到Yahoo帐户






    总结

    通过文章中概述的5个步骤你可以实现IBM 框架。这里的一些例子和代码片断都是跟 Rational Functional Tester 相关的。它们会随着其它IBM 框架的实现是否在使用另外一个工具而有所变化。

  • 扩展RFT的对象识别技术

    2008-06-02 17:53:39

    长期困扰 Rational Functional Tester (RFT) 自动化测试的一个问题就是如何有效地识别 GUI 元素,以适应 GUI 的不断变化,这在敏捷开发日益成为主流开发模式的情况下显得更加重要。本文通过大量的实例向您介绍了针对不同的 GUI 元素,选择不同的对象识别技术,以提高 RFT 自动化测试的效率。

    RFT 对象概述

    RFT 对象

    从开发的角度看,GUI 通常都是基于某一 GUI 开发库(SWT/SWING/AWT),这些库通常是按照面向对象的方式进行建模的,它将每一个 GUI 元素映射成该库中某一个类的对象。

    从测试的角度看,所有的 GUI 元素,无论基于何种 GUI 库,都被 RFT 映射成对象,RFT 提供一个对象模型框架管理各种 GUI 元素。

    图 1 是一个典型的基于 SWT 开发的 GUI,对于其中的一个按钮,在开发者看来,它就是 SWT 库中 Button 类的一个对象;但是 RFT 并不区分这是 SWT 库中的按钮,或者是其他 GUI 库的按钮,它都被映射成 RFT 对象模型中 GuiTestObject 对象。

    在用 RFT 提供的 Inspector 工具获取 GUI 元素时,需要用到开发模型。而进行 RFT 脚本开发时,又需要用到 RFT 对象模型。熟练掌握两种对象模型,对提高 RFT 自动化测试效率非常有帮助。


    图 1. RFT 对象模型示例
    RFT 对象模型示例

    RFT 对象识别

    基于 RFT 的自动化测试,都会采用 IBM 推荐的 ITCL 框架。在这个框架下,所有的脚本被划分为三个层次:对象层,任务层,用例层。对象识别就是在 RFT 的对象模型框架下,得到被测程序的 GUI 对象。它是对象层开发中最核心的任务。

    常用的 RFT 的对象识别技术可以分为两大类:静态识别与动态识别。动态和静态方法各有优缺点,静态方法识别效率高、开发成本比较低,但是脚本的可维护性比较差;而动态方法刚好相反。







    扩展 RFT 对象识别技术

    采用常用的对象识别技术,可以识别出大部分的 GUI 元素,但有时也会遇到 RFT 无法识别的 GUI 元素,事实上识别这类用常用对象识别技术无法识别的 GUI 元素占用了 RFT 脚本开发的大部分时间。

    RFT 中一个非常重要的根接口是 IGraphical 接口,它定义了针对 GUI 元素的所有标准操作(click,doubleclick,drag 等)。另外一个非常重要的根类是 GuiTestObject,它继承自 TestObject 并实现了 IGraphical 接口。常用对象识别技术中 GUI 元素都是被映射为 GuiTestObject 对象。它们在 RFT 对象模型中的位置如图 2 所示。灵活运用这些类、接口及其方法,能够极大地扩展 RFT 对象识别的功能。


    图 2. RFT 对象模型类图
    RFT 对象模型类图
    • 问题描述

    使用 RFT 经常听到的一个谬论就是 RFT 只能测试基于 java 的 GUI 程序,对于 C/C++ 或者 windows 标准控件,RFT 无法识别。事实上,RFT 提供了 IWindow 接口用于识别平台相关的控件。

    • IWindow 接口介绍

    从图 2 中可以看出,IWindow 接口也继承自 IGraphical 接口,从这点看,IWindow 接口具有与 GuiTestObject 类似的功能。

    使用 IWindow 接口能够识别平台相关的 GUI 控件,但是其接口函数的具体实现与平台相关,windows 与 linux 上的实现就不一样,可以通过下述方法判断具体的平台,本文将主要分析 windows 上的应用。


    清单 1
    清单 1
    • 典型应用

    图 3 是记事本的“页面设置”对话框,是一个 windows 原始窗体。如何识别这个窗体,并点击“确定”按钮呢?基于 RFT 的实现方法如下:


    图 3. 被测试程序 GUI
    被测试程序 GUI

    确定对象识别的起始点。通常选取最上层窗体作为对象识别的起始点,具体方法如下所示:


    清单 2
    清单 2

    这些方法都返回一个 IWindow 接口的数组,每一个数组元素代表一个顶层窗口,并且这些窗口之间是互相独立的。

    识别符合要求的顶层窗口,即“页面设置”对话框。IWindow 接口提供了两个方法:getText() 与 getWindowClassName() 来实现。对于窗体,getText() 返回窗体的标题;对于控件,getText() 返回控件的文本。getWindowClassName() 返回 win32 标准控件名。如何知道被测程序的标准控件名呢?在 windows 上有许多工具,例如下文中将提到的 AutoIt 以及 Visual Studio 提供的 Spy++。图 4 是用 AutoIt 得到的 GUI 元素的属性。


    图 4. 利用 AutoIt 得到 GUI 元素的属性
    利用 AutoIt 得到 GUI 元素的属性

    对顶层窗体数组根据文本值和标准控件名进行匹配,则可以识别出符合要求的顶层窗体。这两个方法均返回字符串,为了提高识别的效率,通常对这些字符串进行正则表达式匹配。具体用法如下,参数 sCaption 表示窗体的标题,sWindowClassName 表示窗体的 Win32 标准类名。


    清单 3
    清单 3

    识别窗体内的控件,即“确定”按钮。以顶层窗口为起点,通过 IWindow 提供的 getChildren() 函数可以得到内嵌在顶层窗体的 GUI 控件(如 button,label 等),该方法返回 IWindow 接口的数组,对数组元素根据文本值和标准控件名进行匹配,即可识别出内嵌的控件。识别内嵌控件的方法如下,参数 iTopwin 表示顶层窗体,sCtrlText 表示控件的文本值,sCtrlClassName 表示控件的 Win32 标准类名。


    清单 4
    清单 4

    IWindow 还提供了 getOwned() 方法,可以得到出顶层窗体拥有的子窗体(如模式对话框等)。

    完成点击“页面设置”窗体中“确定”按钮的 RFT 脚本如下。


    清单 5
    清单 5
    • 问题描述

    在进行 GUI 自动化测试时,一个经常遇到的问题就是如何测试开发者定制的控件?通常一组定制的控件,是作为一个整体被 RFT 识别出来,你可以对这个整体作一些操作,但是如何识别出每一个具体的定制控件呢?可以使用 TestObject 类提供的方法:Invoke 函数。

    • Invoke 方法介绍

    Invoke 方法类似于 java 中的反射机制,它可以在运行时而不是编译时调用函数。通俗地说,在 RFT 中,它可以根据字符串来调用相应的函数。这使得不仅可以调用某些确定的方法(如 GuiTestObject 的方法),还可以主动查询定制控件本身提供的方法,大大加强了对象识别能力。

    • 典型应用

    使用 Invoke 函数的一个典型例子就是测试 Notes 8 的 tab 项。Notes 8 的 tab 项是一个定制的 java 控件。RFT 会将多个 tab 项识别为一个 GuiTestObject 对象,如何识别出每一个 tab 项呢?并执行关闭 tab 项的操作呢?

    首先采用 Object map 方法识别出 RFT 能够识别出的最小的定制控件的集合。如下图 2 红色方框所示的 GUI 元素是 RFT 所能识别出的最小的对象。在本例中它被识别为 GuiTestObject 的对象:sTabFolderObject。


    图 5. Notes 8 中定制控件
    Notes 8 中定制控件

    图 5 Notes 8 中定制控件

    确定需要调用的方法。调用 Invoke 方法需要事先知道方法的名称,TestObject 提供了另外一个方法:getMethods 它能够返回控件所有的方法,你可以按照如下的方式调用它。


    清单 6
    清单 6

    按照这种方式,能够在控制台打印该控件所有可用的方法,从中分析出需要的方法。在本例中发现 getItems 能够返回所有的 tab 项。

    调用 Invoke 方法识别出具体的定制控件。完整的用法如下所示,参数 name 表示希望识别的 tab 项的文本值,sTabFolderObject 为上述红色方框表示的对象。


    清单 7
    清单 7

    完成关闭 tab 项操作。利用 Invoke 可以很便捷的操作 GUI 对象,但是一定要避免使用用户所不能操作的方式来操作控件,因为这违背了测试的原则。从 getMethods 返回的方法中发现 dispose 方法也可以关闭 tab 项,但很显然用户不能这样操作,而用户关闭 tab 项的操作就是点击 tab 项的“X”。因此在 RFT 脚本中,可以首先得到“X”的坐标,然后在该点执行单击操作。具体的方法如下所示。


    清单 8
    清单 8






    集成第三方自动化工具

    • 问题描述

    使用 RFT 进行自动化测试时,经常遇到这样的尴尬,一方面 RFT 在识别某些对象时遇到一些问题,比如无法识别,识别效率低,开发识别脚本代价很高。另一方面又有大量的第三方 GUI 自动化工具对某些特定的领域有很好的性能。如果能够结合 RFT 与其他自动化工具,就能够极大地提高自动化测试的效率,更加适应敏捷开发与测试。

    • AutoIt 介绍

    AutoIt 是一种在 windows 平台上,针对 C/C++ 以及 windows 标准控件的,免费、开源的自动化管理工具。AutoIt 本身有一种非常简单的脚本语言,这种脚本语言类于 Basic,并且其脚本可以直接转化为可执行程序且不依赖于任何库。事实上,AutoIt 的这些功能,RFT 提供的 IWindow 接口也能够完成,但 AutoIt 具有更高的效率。

    • 典型应用一

    仍然以 IWindow 接口中点击“页面设置”对话框中的“确定”按钮为例。介绍如何结合 RFT 与 AutoIt 完成上述操作。

    1. 开发 AutoIt 脚本。AutoIt 对 GUI 对象的识别区分 windows 和 controls。对于 windows 是通过 title/text 方式进行对象识别;对于 controls 是通过 title/text/controlID 方式进行识别。ControlID 是 AutoIt 中特有的概念,它不是一个特定的值,可以是:内部 ID,text,class,instance,classmn 以及它们的组合。在本例中,最终需要识别的对象是“确定”按钮,同时它又位于“页面设置”窗体中。具体的 AutoIt 脚本如下。

    清单 9
    清单 9
    1. 在 RFT 中调用 AutoIt 脚本。RFT 提供了多种启动其它进程的方法,其中类 RationalTestscrīpt 提供的 startApp 和 Run 方法比较常用。使用 startApp 需要事先在 IDE 中进行配置,而 Run 方法具有更多的普遍性,具体的调用方法如下。

    清单 10
    清单 10
    • 典型应用二

    在 RFT 中一类经常遇到的问题就是如何处理那些非预期的活动窗体。例如,点击安全网页上的 link,而这个 link 所指向的却是一个非安全的网页,如果浏览器对安全性要求较高的话,就会弹出一个对话框询问你是否仍然打开这个页面,如果选择“是”则下次重复这样的操作将不再会弹出对话框进行询问,否则下次仍然会询问。因此是否会出现这个窗体取决于是否建立了信任关系,而在脚本开发时是无法预见的。

    采用常用的对象识别技术,其典型的处理方法如下所示。


    清单 11
    清单 11

    上述处理方法采用了常用的对象识别技术识别那些非预期的窗体,如果这些窗体无法用常用方法识别,如何来处理这类问题呢?


    图 6. 非预期的对话框
    非预期的对话框

    图 6 是打开网页前,系统弹出的一个对话框,它是一个 windows 原始窗体,无法采用常用方法识别(当然可以用 IWindow 来识别),以下结合 RFT 和 AutoIt 来处理。

    1. 开发 AutoIt 脚本。AutoIt 脚本的任务是点击“Security Alert”对话框中的“Yes”按钮。这可以分为两步,第一步判断对话框是否已经存在;第二步点击“Yes”按钮。具体的 AutoIt 脚本如下所示。

    清单 12
    清单 12
    1. 开发 RFT 脚本。RFT 脚本有三个任务,第一是点击安全网页上的 link 使得“Security Alert”对话框出现。第二是调用 AutoIt 脚本关闭弹出的对话框。第三是判断非安全网页是否已经打开。具体的 RFT 脚本如下所示。

    清单 13
    清单 13

    从以上可以看出,相比单纯使用 RFT,基于 RFT 与 AutoIt 的混合解决方案需要的脚本显著减少,大大提高了脚本开发效率。当然这种混合解决方案需要你对 AutoIt 有一定的了解,增加了学习的负担,但是一旦掌握,对于提高自动化测试效率是很明显的。






    总结

    本文阐述了各种不同的对象识别技术,其中 IWindow 接口用于识别 windows 标准控件;Invoke 方法用于识别应用程序定制的 GUI 控件;此外还介绍了 windows 平台上一款优秀的自动化工具 AutoIt 以及如何与 RFT 结合进行自动化测试。将 RFT 常用的对象识别技术与这些特定条件下的对象识别技术相结合,能够使得 GUI 自动化测试更加敏捷。

  • RFT实现可复用的测试框架

    2008-06-02 17:22:06

    IBM Rational Functional Tester 6.1 可以使测试人员创建现代的、基于模式的、可复用的测试框架。此篇优秀的文章将告诉您如何进行。

    可复用测试框架的情况

    由 John D. McGregor 博士创建的测试设计模式, 为面向对象的组件测试设计一个架构,规定了以下内容:“测试软件的基础体系结构常常被设计成有益于跨许多应用程序和测试解决方案。一般的功能是作为测试许多不同类型组件的基础并作为标准工具的接口。” 同许多测试设计模式一样,该模式立即说明了常常模糊的测试问题,也就是测试代码的重复,并阐明了可能的解决方案:创建了一个可复用的测试框架。

    要创建一个可复用的测试框架您都需要什么呢?最核心的,您需要一个组成测试方法学的对象(如各种测试设计模式中描述的)和被测对象(如各种 GUI 控件所表明的)之间的抽象层。此种抽象会要求具备完全面向对象程序设计语言的功能,它是一个具有健壮的映射方法的语言。您当然会需要一种识别 GUI 控件并以面向对象方式显露出其属性的技术。还需要的是一个知道所有控件及验证 GUI 控件对象方法的集成开发环境。最后,一个允许包含多种辅助工具的足够开放的环境会帮助创建最有效的框架。

    包含所有这些特性的工具使用起来会足够简单,并且它能够使测试专业人员便于管理,这种工具可以被当作一种框架。当你想节省测试所有被测试应用的时间时,花费时间创建一个可重用的测试框架会导致整体时间的节约。在 Eclipse 集成开发环境中运行的 IBM® Rational® Functional Tester 6.1(参见图 1)提供所有这些功能。Functional Tester 有两种版本:VB.NET 脚本(在 Visual Studio .NET 集成开发环境中运行)和 Java™脚本版本(在 Eclipse 环境中运行的)。本文中考虑 Java 脚本版本。因为现在已经有一个可以创建可复用测试框架的产品了,所以没理由不开始。


    图 1. IBM Rational Functional Tester 6.1版本(功能测试透视图)
    IBM Rational Functional Tester Version 6.1 的 Functional Test Perspective 窗口






    测试模式方法

    一旦您拿到了 Functional Tester 工具,就可以开始创建可复用的框架了。但您从哪里开始?您如何进行?有指导吗?幸运的是,在您之前已经进行了一些工作。在其他类型的软件设计模式中,已经创建了许多测试设计模式。当然,它们并没有包括所有需要的东西以创建可复用的测试框架,但值得进行参考。重复了使用模式的好处:

    • 它们为问题解决者提供一个词汇表。“嘿,你知道吗,我们应该使用一个 Null Object。”
    • 它们关注问题背后的力量。其使设计者更好地理解何时以及为什么应用解决方案。
    • 它们鼓励迭代思考。每个解决方案创建一个新的在其中可以解决新问题的环境。





    可复用的测试框架的需求

    现在我们有了工具(Functional Tester)并且我们有了设计方法。是时候回顾一下需求了。我们将看到许多 Functional Tester 能够直接满足的需求,同时也要专注于我们必须添加的以创建可复用框架的一般功能。目的是设计具有以下新功能的测试框架:

    • 自动的测试输入生成
    • 自动的预期结果生成
    • 自动的比较器

    这些功能出自 Robert V. Binder 的 测试面向对象的系统模型、模式和工具 。书中列出许多更多的需求,然而,剩下的要么是由 Functional Tester 自动处理的,要么对一般解决方案不是必要的。







    自动测试输入生成

    在 Functional Tester 提供的功能中,脚本被记录,并且测试人员执行以下工作:将脚本模块化、数据驱动想得到的输入、创建想得到的验证点,并回放脚本。然而,如果测试用例的数量很大的话,问题会出现。在此情况下,需要记录所有测试用例步骤的时间可能不能实行。当联系到许多测试工程上时,该问题扩大了。解决方案是提供用于生成可在所有测试工程中复用的测试输入的一般框架。

    自动生成测试输入有三个主要的方法:

    • Functional Tester 数据池(可以由 IBM® Rational® TestManager 数据库导入)
    • 简单地,通过编程方法控制的 XML 或关系数据库的获取和设置
    • 由算法的生成和过滤作为参数的,通过编程方法控制的 XML 或关系数据库的获取和设置

    每个方法在一般测试框架中都有一个有效的角色。

    方法一:使用: Functional Tester 数据池输入信息

    Functional Tester 数据池用于生成不需要由复杂算法(例如 Address,或 Phone 字段)衍生而来的可变数据。您可以利用 IBM Rational TestManager 数据库池创建的自动格式化特性来创建简单的模式,如社会安全码、名和姓、地址和邮政区码。然后,Functional Tester 可以导入这些数据池(参见图 2)。


    图 2. 导入数据池
    导入先前在 IBM Rational TestManager 中创建的数据池

    在导入之后,您使用 Functional Tester 关联数据库和您的脚本。Functional Tester 允许您选择哪一项用数据池值来替代。您可以通过索引或脚本中的名称查阅到数据池字段。在引用创建之后,如果需要,这些值可以通过编程的方式改变。下载必要的代码,以插入到文中底部的数据池值中。

    方法二:通过简单地检索 XML 或关系数据来输入信息

    简单的说,当只需要一般算法时,通过编程方法控制的 XML 或关系数据库的获取和设置是有用的,但数据模式对于生成的数据池输入仍旧是太复杂。一个实例是自动生成持续的帐户或一般的分类帐户,在其中嵌入了一些语义,并且希望在那样的测试数据中维持真实性,特别是数据涉及非常大的必须在测试程序执行之间保持顺序的数字。此处最有利的解决方案是创建测试数据库并通过编程的方式从那些行中获取输入数据,执行任意需要的语法分析,在 Functional Tester 中按需要使用数据,在 Functional Tester 中从一个脚本到另一个脚本进行数据更新,并更新或将带有在下一个测试程序执行中使用的数据的行插入到测试数据库中。

    您需要为您使用的数据库安装数据库驱动。对于本文中描述的测试框架,创建 SQL Server 测试数据库。要想加强 Functional Tester 类的内聚力,您可能想要将代码与实际的和测试数据库的交互隔离开来,并只是将 SQL 语句作为这些方法的参数进行传递

    如果您想要为测试框架提供来自 Functional Tester 脚本的基于 SQL 的数据库调用的最大化的抽象,您可以实现设计模式 Mapper 和 Query Object,其允许您对 Functional Tester 脚本中的信息进行一般化的请求,以服从具体数据库 SQL 语法到其他类的构造。

    方法三:输入数据算法的生成

    通过算法从 XML 或关系数据库中检索数据来有计划地生成输入数据是一般测试框架的核心引擎。本文介绍了一个方法三的版本,其中实现了设计模式 Combinational Function Test。在此模式中,由每个输入值组合生成的操作被评估。

    一种用于存储一组 GUI 控件的可能输入值的有效方法是将控件及其可能的值放入 XML 文件中。随着当前这种应用开发中的动态的、执行时决定显示哪个控件的趋势,现在有一个好的机会,您项目的开发团队已经在 XML 配置文件中定义了控件和其可能的值。但如果他们没有,您就可以在几分钟之内做出那样一个 XML 文件。(在本文的底部下载 GUI 控件和其可能值的示例 XML 描述)。您可能想要通过任意组合框的下拉列表提交值。对于文本框,您可以提交导致各类业务规则的结果值的具体实例(比如,提交 1 和 12,如果业务规则规定 0 和 10 之间的值会导致一个结果,而 11 和 20 之间的值会导致另一个结果)。

    提交条件式来代替值是可能的(例如 "< 20)。这需要一些额外的编码来分析条件式,这可能会十分复杂(参阅 可重用的面向对象软件的设计模式元素 中的 Interpreter 设计模式)。

    要访问 XML 文件,我们将利用文档对象模型(Document Object Model,DOM)。此方法需要比其他方法更少的编程并在将所有 XML 访问代码保留在 Functional Tester 类中方面占有优势。使用 DOM 的通常劣势是需要许多内存,但当需要为应用程序定义 GUI 控件的 XML 文件很小时是不成问题的。如果您测试经常变化的应用程序,可以考虑更简单的维护,来为每一屏创建单个的 XML 文档,或一些其他的逻辑分割。一旦您理解了文档遍历方法,对包含 GUI 控件和对于这些控件可能的值的 XML 文件的 DOM 分析就相当的简单了。基本上,您创建类来设置 DOM 使其与 XML 文档一起工作,过滤 XML 节点,并处理过滤器的结果。下载本文底部的代码进行所有这三个动作。

    如这三个类所描述的,本文中的策略是通过指定以下内容来检索节点的:

    • 期望节点的根
    • 期望节点的父节点
    • 期望节点的名称

    过滤器还指定达到对照节点所必要的兄弟节点的数量。为了便于使测试框架一般化,您应该使用变量对应那些值作为这些过滤节点的名称,并在中央位置设置这些变量的值。这使得配置下一个在测应用程序的测试框架更加简单。使用像 Functional Tester 这样的现代工具的一个意义是使得将强大的应用程序,如 DOM 引入到复杂的任务中(如创建一般化的测试框架)来进行辅助成为可能

    使用 Functional Tester 的另一个意义是,根据其对 Java 的支持,它对 Collection(创建任何种类的框架所绝对必要的)提供很强的支持。在此处描述的测试框架中,所有 Combinational Function Test 模式实现所涉及到的 GUI 控件的名称和可能的输入值存储在一个Vectors的Vector中。此超级Vector索引为 0 的Vector包含了每个参与实现的 GUI 控件的名称。每个余下部分的Vector包含了每一个参与GUI 实现的控件的可能输入值。创建框架时必须完成的一项任务是构造一个等同于每个 GUI 控件可能拥有的三个名称的映射:XML 文件、被测应用程序代码和 Functional Tester Test Object Map。您可以生成一个使用正规表达的类,或者如果您企业中的命名标准严格限定,您可以进行简单的编辑。

    既然我们将所有参与的输入值存储到Vectors中,那我们就可以开始生成所有可能组合的工作了。此处使用的方法是递归形成存储在每个 GUI 控件可能值Vectors 中的值的积(我们称这些Vectors为“置换群(Permutation Group)”)。我们开始形成包含一组 ArrayLists 的 ArrayList,在其中,每个构成的 ArrayLists 正好包含第一个置换群的一个元素。然后,创建一个新的 ArrayList,它包含每个(超级 ArrayList 的)构成的 ArrayLists 的内容和第二个置换群的所有单元的向量积。伴随每个递归步骤,会形成带有一个额外置换群的向量积。

    在过程的最后,我们有一组 ArrayLists(测试用例),每个都包含对应参与的 GUI 控件的有效值(下载本文底部的代码。)。ArrayLists 中值的顺序与 XML 文件中的 GUI 控件的顺序是一致的(回去参考 XML 文件配置的代码)。您的框架应该为每个测试用例分配一个数,为了简单地再次运行失败的测试用例。

    减少生成测试用例的数量

    当然,处理测试输入的所有可能的全排列输出很快就行不通了(依据在测的应用程序)。例如,如果您有十个参与的 GUI 控件,并且如果每个控件只取三个可能的值,您将生成 59,049 个测试用例!有许多方法限制该数量。最简单的方法是在 XML 文件中加入标志,使得只考虑临界的 GUI 控件和值。另一种方法是让框架生成所有的测试用例,但只处理第一个 n,或者只处理随机选择的(可以在一个单个的,全世界都容易接受的类中定义这些选择标准的参数,以简化对每个在测应用程序的变量配置)。其他方法还涉及在代码中调用生成测试用例的业务规则(就是说,“如果 GUI 控件 A 的值小于 20,但 GUI 控件 B 的值大于 12,那么删掉该测试用例”)。







    预期结果的自动生成

    一旦创建了用于自动生成测试输入的类,您就可以创建使用这些输入的 Functional Tester 脚本了。此处的整个方案是遵循由 John D. McGregor 博士创建的一个版本的测试设计模式:利用测试脚本的顺序测试用例,及 Robert V. Binder 创建的测试设计模式:Test Case/Test Suite Method。我们的测试框架的整个结构是具有一个单个控制器的测试脚本,它执行两个功能:1) 在先前的测试脚本之后进行清除,并设置后续脚本,及 2)调用其它模块化的测试脚本。这些模块化脚本越是紧密,就越能更好地促进脚本的复用性。用于调用其它脚本的 Functional Tester Java 语法是:callscrīpt ("OtherModularizedscrīptName");。有所帮助的是将控制器脚本中的 callscrīpt 语句用 System.out.println 语句(在控制台中书写注释,指示在处理控制器脚本过程中发生的事件的顺序)进行分离。

    假设被测的应用程序有大量的测试用例,我们承认记录每个测试用例以创建模块化的测试脚本必须预先有利于一个更一般化的解决方案。Functional Tester 工具使我们实现 Prototype 设计模式(Design Patterns Elements of Reusable Object-Oriented)以在执行时选择期望的功能测试方法。这可以通过利用反射在 Functional Tester 助手类中参数化地调用方法来完成(下载本文底部的代码)。在记录脚本时,Functional Tester 会自动生成这些助手类。

    Functional Tester 助手类中包含了到被测应用程序中的 GUI 对象的索引。Functional Tester 的向 Test Object Map 中添加 GUI 控件的概念(可由多个测试脚本使用)有效地实现了 Fowler 的 Identity Map 设计模式。Functional Tester 通过测试人员执行的两步骤的过程获得了这些 GUI 对象的属性:

    1. 使用 Functional Tester GUI 控件识别工具。更确切地说,将“手”图标(参见图 3)拖到控件上,释放以向 Functional Tester Test Object Map 中输入对象。
    2. 将 Test Object Map 添加到需要访问该控件的测试脚本中(在 Functional Test Perspective 顶部菜单栏:选择scrīpt > Open Test Object Map > select an object > Add to scrīpt)。

    图 3. Drag Hand Selection 方法
    Functional Tester 对象识别的 Drag Hand Selection 方法

    利用上面概括的过程,您应该能够创建模块化的、可复用的,由您所创建的测试脚本控制器调用的脚本。然而一个错过的内容是动态控制测试程序的方法。对此,您的测试框架可以使用一个 GUI 接口,通过它测试团队可以控制运行时参数(当然,在您的测试控制器脚本启动时,Functional Tester 也允许您输入命令行参数)。幸运的是,Functional Tester 允许您访问任何您要用 Standard Widget Toolkit((SWT)来创建的 GUI。

    首先,您需要将 SWT 安装到 Functional Tester(Eclipse)环境中(查阅书籍 SWT A Developer's Notebook 中的逐步的指导)。假如我们想要一个可以输入某些运行时参数的简单对话框窗口。然后您需要生成一个 SWT 外壳类和对话框窗口本身的类(下载本文底部的代码)。完成了的测试框架执行时的对话框窗口如图 4 显示。


    图 4. SWT 输入对话框窗口的运行时显示
    SWT 输入对话框窗口的运行时显示






    自动比较器

    既然您的测试框架中包含了输入测试用例数据和执行测试用例的一般化机制,那么您就需要一个自动验证结果的方法。存在许多比较基线数据和实际结果的可用选择。Functional Tester 提供三种类型的验证:静态、手动和动态(在 Functional Tester Help 中搜索主题 IftVerificationPoint,以得到完整的描述)。要创建一个一般的测试框架,您最好的选择可能是手动,因为其考虑最大化的编程控制和有效的、高容量的验证。当然,您也可以书写自己的代码,但 Functional Tester 方法已经将结果写到 Playback 日志中。因此,您的测试框架会包含脚本,如:vpManual("vpResultChecker1", strExpectedResult, strActualResult).performTest();

    然后,您会从 XML 文件或关系数据库表格中读到预期的结果。您会想将每个测试用例 ID 与一致的期望结果关联起来。在大容量的测试环境中,您也许还想创建 GUI 来显示所有的验证失败(参见图 5)。


    图 5. 显示验证差异的 GUI 示例
    显示验证差异的 GUI 示例





    结束语

    现在您拥有了一般测试框架的核心。Functional Tester 提供其两个自身直接的支持,以及通过其开放的体系结构对其他辅助产品的支持。与您曾想要实现的其他更简单的测试设计模式要做的事情相比,本文中的实例相当复杂。当然,如早些时候陈述的,Functional Tester 本身已经实现了很多简单的满足可重用测试框架的需求。其他的需求你也可以在 Functional Tester 中很容易实现。具备了这样一种通用的测试框架,您可以在将来的测试工程中大大地减少测试时间。

  • RFT 助您轻松完成自动化功能测试

    2008-06-02 17:17:05

    本文将向读者介绍 IBM Rational Functional Tester 的强大的功能和良好的易用性,以及如何帮助测试人员轻松的完成自动化的功能测试。

    1 解析自动化测试的困惑

    在软件工程领域,如果说有一种工作让人在痛苦中感受它的价值、在无休止的加班中体会它的苦涩、在技术的进步中体验它的快乐的话,那它一定是软件测试。计算机技术发展到今天,自动化测试工具的广泛应用使人们重新认识到测试的源动力:最优的质量成本,软件开发过程中的测试及各种质量保证活动,无疑是在追求软件质量成本和收益间的最佳平衡点。

    谈到自动化测试,首先我们要明确什么情况下需要自动化。自动化测试的目的是通过自动执行测试脚本,使测试人员在更短的时间内能够更快地完成更多的软件测试,并提供以更高的频率执行测试的能力,从而有效降低测试成本、提高测试效率。从软件测试的成本来看,使用测试工具进行软件自动化测试的成本可以以下公式表示:

    自动化测试的成本=测试工具成本+测试脚本的创建成本+测试脚本的维护成本

    既然自动化测试的目的在于降低测试成本、提高测试效率,因此,测试团队在选择自动化测试工具时,必须在提高测试效率的同时,尽量做到自动化测试的总体成本小于手工测试成本。因此,自动化测试工具的脚本自动化创建能力和可维护性,就成了衡量自动化测试工具的重要因素。

    在实际的测试工作中,一般说来,我们选择自动化的功能测试工具无外乎要解决以下三个问题:

    • 自动化的功能回归测试
    • 大批量数据驱动的软件测试
    • 整个软件测试生命周期的管理

    在选择自动化测试工具解决这些问题的过程中,人们主要关心的问题是使用自动化测试工具创建测试脚本的能力、工具的易用性、测试脚本的编程和扩展能力、测试脚本的参数化技术以及作为软件开发重要环节的测试工作和其它软件生命周期管理工具的集成能力。

    因此,摆脱自动化测试困惑的根本途径,就是理解自动化测试的本质,明确自己的自动化测试需求,选择合适的自动化测试工具,帮助测试团队提高效率、降低成本,最终实现软件开发过程的全过程质量保证。







    2 IBM最新自动化功能测试解决方案:Rational Functional Tester

    IBM Rational Functional Tester(简称RFT)是一款先进的、自动化的功能和回归测试工具,它适用于测试人员和GUI开发人员。使用它,测试新手可以简化复杂的测试任务,很快上手;测试专家能够通过选择工业标准化的脚本语言,实现各种高级定制功能。通过IBM的最新专利技术,例如基于Wizard的智能数据驱动的软件测试技术、提高测试脚本重用的scrīptAssurance技术等等,大大提高了脚本的易用性和可维护能力。同时,它第一次为Java和Web测试人员,提供了和开发人员同样的操作平台(Eclipse),并通过提供与IBM Rational整个测试生命周期软件的完美集成,真正实现了一个平台统一整个软件开发团队的能力。






    3 使用IBM RFT轻松完成自动化功能测试

    3.1 基于与开发人员同一开发平台的功能测试

    IBM RFT的最大特色就是基于开发人员的同一开发平台(Eclipse),为Java和Web测试人员提供了自动化测试能力。如图一所示,使用RFT进行软件测试时,我们只要在开发人员工作的Eclipse环境中打开Functional Test透视图,就会马上拥有专业的自动化功能测试工具所拥有的全部功能。


    图一、IBM Rational Functional Test工作界面
    图一、IBM Rational Functional Test工作界面

    在RFT中实现测试脚本的过程和大部分的自动化测试工具一样,是基于录制的脚本生成技术。当我们完成测试用例后,只要在功能测试工具条上选择测试脚本录制按钮,就会启动测试用例的脚本实现过程。

    如图二所示,在脚本录制的"选择脚本资产"对话框中,用户可以选择预定义好的公用测试对象图和公用测试数据池,也可以选择在脚本录制过程中生成私有测试对象图和数据池。测试对象图是IBM用来解决测试脚本在不同被测版本间,成功回放的关键技术,它为测试脚本的重用提供了重要保证;而测试数据池是IBM用来实现数据驱动的自动化功能测试的重要手段,使用智能化的数据驱动测试向导,测试脚本的参数化几乎变得易如反掌。


    图二、"选择脚本资产"对话框
    图二、选择脚本资产对话框

    如图三所示,在功能测试的录制监视窗口,测试员可以根据提示启动被测应用系统,执行测试用例中规定的测试步骤,实现测试脚本的录制。在测试脚本录制过程中,测试员可以根据需要插入验证点和数据驱动的测试脚本,验证点是在指令中比较实际结果和预期结果的测试点,自动化功能测试工具正是通过它实现对被测系统功能需求的验证。


    图三、测试脚本录制窗口
    图三、测试脚本录制窗口

    完成脚本录制过程以后,RFT会自动生成用工业标准语言Java描述的测试脚本,如下所示:


    import resources.ThirdwithDatapoolHelper;
    import com.rational.test.ft.*;
    import com.rational.test.ft.object.interfaces.*;
    import com.rational.test.ft.scrīpt.*;
    import com.rational.test.ft.value.*;
    import com.rational.test.ft.vp.*;
    /**
     * Descrīption   : Functional Test scrīpt
     * @author ndejun
     */
    public class ThirdwithDatapool extends ThirdwithDatapoolHelper
    {
    	/**
    	 * scrīpt Name   : <b>ThirdwithDatapool</b>
    	 * Generated     : <b>2005-4-17 15:22:36</b>
    	 * Descrīption   : Functional Test scrīpt
    	 * Original Host : WinNT Version 5.1  Build 2600 (S)
    	 * 
    	 * @since  2005/04/17
    	 * @author ndejun
    	 */
    	public void testMain(Object[] args) 
    	{
    		
    		startApp("ClassicsJavaB");
    		
    		// Frame: ClassicsCD
    		classicsJava(ANY,MAY_EXIT).close();
    	}
    }
    

    基于Java的测试脚本,为高级测试软员提高了更强大的编程和定制能力,测试员甚至可以通过在Helper类中加入各种客户化脚本,实现各种高级测试功能。

    3.2 使用RFT轻松实现数据驱动的软件测试

    RFT具有基于向导(Wizards)的数据驱动的功能测试能力。在功能测试脚本的录制过程中,如图四所示,我们可以方便选择被测应用图形界面上的各种被测对象,进行参数化,通过生成新的数据池字段或从数据池中选择已存在数据字段,实现数据驱动的功能回归测试。


    图四、数据驱动的功能测试
    图四、数据驱动的功能测试

    在生成测试脚本的同时,RFT还能够帮助测试员在验证点中使用正则表达式或使用数据驱动的方法建立动态验证点。动态验证点用来处理普通验证点的期望值随着输入参数不同而发生变化的情况。在下面的例子中,如图五所示,订单总金额会随着购买商品数量的不同而变化,通过数据驱动的功能测试方法,测试员首先要对购买的商品数量和订单总金额进行参数化,然后编辑验证点中的期望值,将其用数据池中的对应订单总金额代替,这样验证点中的总金额就随着购买商品数量的不同而得出正确的总金额。通过简单操作、无需任何编程,测试员就可以很方便地实现动态验证点的功能。


    图五、生成动态验证点
    图五、生成动态验证点

    此外,测试员还可以通过在验证点中使用正则表达式,建立更加灵活的验证点,保证测试脚本的重用性。


    图六、正则表达式在验证点中的应用
    图六、正则表达式在验证点中的应用

    3.3 提供多种专利技术,提高脚本的可维护性

    使用IBM Rational Functional Test工具进行Java和Web应用系统测试时,标准Java的测试脚本语言,为测试脚本的可重用性和脚本能力提供了第一层保证。此外,通过维护"测试对象图",IBM为测试员提供了不用任何编程就可以实现测试脚本在不同的被测系统版本间的重用能力。"测试对象图"分为两种,一种是公用"测试对象图",它可以为项目中的所有测试脚本使用;另一种是私有"测试对象图",它只被某一个管理的测试脚本所使用。在软件开发的不同版本间,开发员会跟据系统需求的变化,修改被测系统和用于构建被测系统的各种对象,所以测试脚本在不同的版本间进行回归测试时经常会失败。因此,通过维护公用"测试对象图",如图七所示,测试员可以根据被测应用系统中对象的改变,更新测试对象的属性值及对应权重,这样在不修改测试脚本的前提下,就能使原本会失败的测试脚本回放成功。同时,为了方便测试员对测试对象图的修改和维护能力,RFT还提供了强大的查询和查询定制能力,帮助测试脚本维护人员快速找到变化的测试对象,进行修改和维护工作。


    图七、测试对象图的维护
    图七、测试对象图的维护

    其次,IBM提供的scrīptAssurance专利技术,使测试员能够从总体上改变工具对测试对象变更的容忍度,在很大程度上提高了脚本的可重用性。scrīptAssurance技术主要使用以下两个参数:脚本回放时,工具所容忍被测对象差异的最大门值和用于识别被测对象的属性权重。使用这种技术,测试员可以通过Eclipse的首选项设定脚本回放的容错级别,即门值,如图八和图九所示:


    图八、IBM专利技术:scrīptAssurance容错级别设定
    图八、IBM专利技术:scrīptAssurance容错级别设定

    点击高级,能够看到各种具体的可接受的识别门值。


    图八、scrīptAssurance门值设定
    图八、scrīptAssurance门值设定

    其次,测试员可以根据被测对象实际更改情况,在测试对象图中(如图七所示)修改用于回放时识别被测对象的属性及其权重。在测试脚本回访时,测试对象的识别分数将由以下公式计算得出:


    int score = 0;
    for ( int i = 0; i < property.length; ++i )
    score += (100 - match(property[i])) * weight;
    

    其中,match()将根据属性的符合程度返回0~100之间的值,完全符合返回100,完全不符合返回0。

    测试脚本回放成功与否则取决于:识别得分 < 识别门值。通过这一技术,如图十所示,通过设置恰当的scrīptAssurance门值和为用于识别对象的属性设置合适的权重,即使在两个回归测试的版本间测试对象有多个属性不同,对象仍有可能被正确识别,脚本仍有可能回放成功。这为测试脚本的重用提供了最大程度的灵活性。


    图十、scrīptAssrance技术保证脚本的重用
    图十、scrīptAssrance技术保证脚本的重用

    3.4 与其它生命周期管理软件的完美集成

    IBM Rational的自动化功能测试工具基于Eclipse平台,提供了和需求管理工具(RequisitePro)、建模工具、代码级测试工具和变更及配置管理工具(ClearQuest和ClearCase)的完美集成,这使得系统测试人员能够和整个软件开发团队在同一个软件平台上,实现系统功能测试,完成测试脚本的配置管理和缺陷追踪。






    4 小结

    如果一种软件工具能够在提供强健的自动化测试脚本录制和自动化测试能力的同时,很好地解决测试脚本的可维护性、大批量数据驱动的软件测试和整个软件开发生命周期的集成问题,它无疑为降低软件测试的质量成本提供了重要保证,而IBM Rational Functional Tester正是这样的工具,它的出现必将使我们的测试生活变得更加美好!

  • Rational Robot 的自动化功能测试框架

    2008-06-02 17:10:58

    本文介绍了构建在 IBM Rational Robot 基础之上的自动化功能测试框架,来帮助组织更好的进行自动化的功能测试。

    1. 前言

    测试本身就是一项异常艰苦的工作,而成功的进行自动化的功能测试,对很多软件开发组织来讲,更是困难重重。本文介绍了构建在IBM Rational Robot基础之上的自动化功能测试框架,来帮助组织更好的进行自动化的功能测试。

    2. 现实的挑战

    2.1 自动化测试的迫切需求

    随着业务的变化,软件产品的种类越来越多,软件产品的升级越来越快,在很多的软件开发组织中,测试部门承受着巨大的压力,他们一方面要测试越来越多的软件产品,一方面要应对越来越短的测试时间,同时,还要面对捉襟见肘的测试资源。

    每个版本发布都包括新增加的功能和已有的功能,已有的功能已经在以前的版本中进行过测试,但是还需要在此版本中执行回归测试。在这种情况下,测试部门往往会考虑到,既然回归测试的测试用例都已经存在并且已经在上一个版本中执行过,那么在新版本中能否自动的执行这些测试?如果能这样的话,将极大的节省时间和资源,将有限的资源投入到新功能的测试上,缓解测试的压力。

    通常情况下,软件开发组织会使用自动化测试工具,使用录制回放方式来进行功能测试的自动化。但是录制回放方式并不能解决全部问题。

    2.2 录制回放中存在的问题

    业界的经验表明,虽然录制回放方式能够快速的生成测试,但是仅仅单纯的使用录制回放是不够的。

    首先,也是最主要的原因,就是使用录制回放方式,往往需要耗费时间和资源来调试、维护脚本。这些工作量随着脚本数量的增加,可能会增大到几乎不可能再对脚本进行有效维护的地步;其次,使用录制回放方式,要求应用已经开发完成并且在录制中不出现错误,但是往往当应用达到此条件时已经没有足够的时间进行测试;最后,使用录制回放方式,要求每个测试人员均会使用测试脚本语言“编程”,而当前大多数软件开发组织测试人员专注于业务,往往没有兴趣和精力来“编程”。

    所以,录制回放方式并不能解决所有的问题,在自动化的功能测试上,需要有测试框架的支持。

    3. 解决之道

    3.1 概述

    IBM Rational Robot是一款优秀的自动化测试工具,自动化功能测试框架是基于Robot之上构建的。如下图:


    图 1. 基于Robot的自动化功能测试框架
    基于Robot的自动化功能测试框架


    业务测试人员类似于当前软件开发组织中使用手工执行测试的测试人员。可以看到,在解决方案中,除传统的业务测试人员外,增加了技术测试人员角色。技术测试人员偏重于自动化测试相关技术,实际上并不直接执行测试。

    解决方案的核心是使用Robot的SQABasic脚本开发的Robot测试技术框架。此Robot测试技术框架以表驱动为指导思想,读入动态结构,解释并执行动态结构中的每一项,是自动化测试的引擎。同时,为了提高Robot测试技术框架的易用性,在解决方案中还包括测试设计工具,它是使用其它编程语言,比如JAVA、Dephi等开发的应用程序。在测试设计工具中,测试技术人员首先建立和待测试应用一一对应的静态结构,此静态结构以页面为单位,随后业务测试人员从静态结构中选择不同的页面,组成测试动态结构,即测试用例,随后,此动态结构被Robot测试技术框架读入并解释执行。

    3.2 Robot测试技术框架

    3.2.1 表驱动介绍

    Robot测试技术框架是基于表驱动测试思想。表驱动测试就是预先在表中定义清楚代表每一步执行操作的关键字,然后由脚本读入表中的每一行,根据关键字来执行对应的动作。以CQ Web登录界面为例:


    图 2. ClearQuest Web登录界面
    ClearQuest Web登录界面


    当要自动执行“登录”按钮时,可以如下图来定义此表:

    登录

    然后在Robot的脚本中,打开表,读入此行并执行。这样的话,Robot便去点击界面上的“登录”按钮了。


     '打开文件
    Dim sData() as string
    InFileName = getExcelFileName
    ReadExcelData InFileName, sData()
    
    ===============================
    
    ‘解释并执行
    Select Case (sKeyWord)
    Case "登录"
          Window SetContext, "currentwindow", ""  
          PushButton Click,  "Text=登录", ""
    


    以上是表驱动的简单示例。在自动化测试中,基于表驱动,还需要解决以下问题:对象识别、验证点、数据池、分支执行、数据关联、日志记录、调用其它脚本、脚本结束。本节将分别展示其在Robot测试技术框架中的实现方式。

    3.2.2 对象识别

    根据IBM Rational Robot识别对象并执行操作的要求,如果要让Robot找到界面上的对象并执行相关动作,需要给Robot指定每个对象的对象类型、对象标志、执行动作和数据,如下图所示。


    图 3. 为Robot指定每个对象的对象类型、对象标志、执行动作和数据
    为Robot指定每个对象的对象类型、对象标志、执行动作和数据


    以按钮举例来讲,如果要让Robot自动点击某个按钮,那么首先要告诉Robot需要在“Button”这种类型的对象上进行操作;其次要告诉Robot,在此类型的对象上要执行什么操作,比如click;第三要告诉Robot要click那个具体的按钮上,比如要click“登录”按钮。

    表 2:对象识别表
    动作类型 对象类型 对象标志 执行动作 数据
    G Button 确定 Click
    G EditBox 姓名 Click Jack
    G ComboBox 角色列表 Click 系统管理员
    G RadioButton 区域 Click

    在Robot测试技术框架中,相应的处理为:

     '打开文件
    Dim sData() as string
    InFileName = getExcelFileName
    ReadExcelData InFileName, sData()
    
    ===============================
    
    ‘对文件中每一行
    Select Case (sObjType)
    Case "Button"
        ProcessButton(sObjAction, sObjData, sData)
    Case “EditBox”
        ProcessEditBox(sObjAction, sObjData, sData)
    Case “ComboBox”
        ProcessComboBox(sObjAction, sObjData, sData)
    Case “RadioButton”
        ProcessRadioButton(sObjAction, sObjData, sData)
        
    ===============================
    
    ‘对按钮执行的动作
    Select Case(sObjAction)
        Case “Click”
            Window SetContext, "currentwindow", ""  
            PushButton Click,  "Text=" & sObjData, ""
            
    ===============================
    
    ‘对文本框执行的动作
    Select Case(sObjAction)
        Case “Click”
            EditBox Click, "Name=" & sObjData, ""
            InputKeys "^+{HOME}{DELETE}" 
            InputKeys sData
    ===============================
    
    ‘对组合框执行的动作
    Select Case(sObjAction)
        Case “Click”
            ComboBox Click, "Name=" & sObjData, ""
            ComboListBox Click, "Name=" & sObjData, "Text=" & sData
    
    ===============================
    
    ‘对单选按钮执行的动作
    Select Case(sObjAction)
        Case “Click”
            RadioButton Click, "Name=" & sObjData
            
    

    要强调的是,以按钮为例,虽然在表中需要为界面上每一个具体的按钮定义一行,但是在测试技术框架中,所有按钮处理的代码都是一样的。

    3.2.3 验证点

    没有验证点的自动化测试就不能称之为测试。从这句话中就可以看到验证点在自动化测试中的重要性。对于验证点来讲,因为不同的测试、不同的应用验证点都不相同,所以Robot测试技术框架仅仅提供了扩展的机制,不同的验证点可以通过扩展机制加入到测试技术框架中。

    加入验证点之后,表的定义如下:

    表 3:对象识别表
    动作类型 对象类型 对象标志 执行动作 数据
    G Button 确定 Click
    G HTMLLink 链接 Click
    G ComboBox 角色列表 Click 系统管理员
    G RadioButton 区域 Click
    V VP VP_SUM VP_SUM 24

    最后一行是加入的验证点。所有的验证点其对象类型均为VP,不同的验证点有不同的对象标志,上表中的验证点是VP_SUM,验证点的基线数据为24。

    在Robot测试技术框架中,处理如下:

    ‘对文件中每一行
    Select Case (sObjType)
    Case ……
        Process……
    Case “VP”
        ProcessVP(sObjAction, sData)
        
    ===============================
    
    ‘对验证点执行的动作
    g_VP_SUM_Baseline = sData
    Callscrīpt sObjAction
    
    ===============================
    
    ‘验证点脚本的处理
    sData = g_VP_SUM_Baseline
    SQAGetProperty “”, “”, sActual
    if sData = sActual then
        ……
    else
        ……
    end if
    
    

    将验证点的基线数据放入全局变量g_VP_SUM_Baseline中,然后使用Callscrīpt函数来调用验证点的脚本。对每一个验证点单独的创建一个脚本文件,脚本文件的名字和验证点的标志相同,都是VP_SUM。虽然各个验证点脚本的内容都不相同,但是一般的步骤是首先从全局变量g_VP_SUM_Baseline中取出基线数据,然后使用SQAGetProperty函数从界面上取实际的数据,再比较实际数据和基线数据。

    3.2.4 数据池

    往往需要使用不同的数据来运行同一个测试,在自动化测试中是使用数据池来实现的。数据池的增加比较简单,就是往表中增加表示数据的列,每一列代表一次测试执行所需要的数据。如下表:

    表 4:数据池表a
    动作类型 对象类型 对象标志 执行动作 数据1
    G Button 确定 Click
    G HTMLLink 链接 Click
    G ComboBox 角色列表 Click 系统管理员 普通管理员
    G RadioButton 区域 Click
    V VP VP_SUM VP_SUM 24 24

    从上表中看到,“数据1”这一列代表一次测试的执行所需要的数据,“数据2”代表另外一次测试的执行所需要的数据。

    在Robot测试技术框架中,加入循环,按照数据列的数量来进行循环,每一个循环均从第一行执行到最后一行。

    3.2.5 执行分支

    在测试中,往往是同一个业务或者功能,但是因为输入的数据、选择的条件不同,而具有不同的执行流程。执行分支的处理比较简单,就是在相应的数据列的位置上,填写代表忽略的特殊标志,比如“IGNORE”,当测试执行到此动作时,判断其数据是否是“IGNORE”,如果是,就不执行此动作而到下一个动作。对应的表如下:

    表 5:数据池表b
    动作类型 对象类型 对象标志 执行动作 数据1
    G Button 确定 Click
    G HTMLLink 链接 Click
    G ComboBox 角色列表 Click 系统管理员 普通管理员
    G RadioButton 区域 Click
    V VP VP_SUM VP_SUM 24 IGNORE

    从上表中看到,第一次执行会执行VP_SUM验证点,但是第二次执行,因为验证点相应的数据是“IGNORE”,所以就不会执行VP_SUM验证点。

    在Robot测试技术框架中,在每次执行动作时,先判断其数据是否是“IGNORE”即可。

    3.2.6 数据关联

    在测试中,需要处理数据关联这种情况。数据关联是指前一个动作执行完成后,应用产生新的数据,此数据在随后的动作中需要用到。因为这些数据是在执行的过程中由程序产生的,所以没有办法预先在表中准备。在这种情况下对应的表如下:

    表 6:数据池表c
    动作类型 对象类型 对象标志 执行动作 数据1
    G Button 确定 Click
    G HTMLLink 链接 Click
    G ComboBox 角色列表 Click 系统管理员 普通管理员
    G RadioButton 区域 Click
    V VP VP_SUM VP_SUM  24 IGNORE
    G DC DC_GETID DC_GETID
    G EditBox 交易号 Click DC_GETID DC_GETID

    从上表可以看到,首先使用DC_GETID来将要关联的数据取出来,然后在需要使用此数据的地方,再使用DC_SETID赋值回去。

    在Robot测试技术框架中,取数据的处理如下:

    ‘对文件中每一行
    Select Case (sObjType)
    Case ……
        Process……
    Case “DC”
        ProcessDC(sData)
    
    ===============================
    
    ‘对数据关联执行的动作
    Callscrīpt sData
    
    ===============================
    
    ‘数据关联中,获取数据脚本的处理
    SQAGetProperty “”, “”, g_DC_ID
    
    

    对每一个数据关联,取数据单独的创建一个脚本文件,脚本文件的名字和数据关联的名字相同,都比如说都叫DC_GETID。虽然数据关联取数据脚本的内容各不相同,但是一般的步骤是使用SQAGetProperty函数从界面上取得数据,放入全局变量g_DC_ID中。

    在Robot测试技术框架中,赋值回去的处理如下:

    ‘对文件中每一行
    Select Case (sObjType)
    Case ……
        Process……
    Case “EditBox”
        ProcessEditBox(sObjAction, sObjData, sData)
     
    ===============================
    
    ‘对文本框执行的动作
    Select Case(sObjAction)
        Case “Click”
            EditBox Click, "Name=" & sObjData, ""
            InputKeys "^+{HOME}{DELETE}" 
            InputKeys g_DC_ID
            
    

    即从全局变量g_DC_ID中取出数据,再输入到文本框中。

    3.2.7 其它处理

    其它处理包括日志记录、调用其它脚本以及脚本结束,相应的表如下:

    表 7:数据池表d
    动作类型 对象类型 对象标志 执行动作 数据1
    G Button 确定 Click
    G HTMLLink 链接 Click
    G ComboBox 角色列表 Click 系统管理员 普通管理员
    G RadioButton 区域 Click
    V VP VP_SUM VP_SUM  24 IGNORE
    G DC DC_GETID DC_GETID
    G EditBox 交易号 Click DC_GETID DC_GETID
    L 输入交易号 输入交易号
    S Order Order
    X

    可以看到,在动作类型这一列,使用使用“L”代表记录日志,日志的内容存放在这一行的数据列中,比如上表中的“输入交易号”;使用标志“S”代码调用其它脚本,要调用的脚本名称存放在这一行的数据列中,比如上表中的“Order”;使用标志“X”代表脚本结束。

    在Robot测试技术框架中,相应的处理如下:

    ‘对文件中每一行
    Select Case (sActType)
    Case “G”
        Process……
    Case “L”
        Log(sData)
    Case “S”
        Callscrīpt sData
    Case “X”
        Exit
        
    

    3.3 测试设计工具

    测试设计工具的最主要的目的就是为了提高Robot测试技术框架的易用性,帮助测试人员生成表驱动所需要的表。另外,测试设计工具通过使用数据库,能够在工具级别为测试重用提供支持。测试设计工具主要包括两方面的功能:供技术测试人员创建测试的静态结构;供业务测试人员创建测试的动态结构。

    测试的静态结构要求和应用保持一致,以页面为单位。即应用中各个功能的层次结构是如何来安排的,就相应的在测试设计工具中按照这种安排来建立静态结构,直到每个页面为止。这样来设计的好处是:首先,静态结构和应用保持一致,将来应用发生变化,比较容易定位到静态结构中需要修改的地方;其次,建立静态结构,应用是什么样子,就建立成什么样子,照搬即可,不需要很多的业务知识,比较适合于技术测试人员;最后,静态结构和应用保持一致,将来业务测试人员设计测试的动态结构时,能够方便的根据应用在静态结构中找到相应的页面。

    以下是已经建好的静态结构的示例:


    图 4. 静态结构示例
    静态结构示例


    可以看到,左边是和应用功能组织保持一致的树形结构。点开“集团理财”节点,可以在右边的上半部分看到此页面中的元素,页面上每一个元素都按照Robot技术框架的要求输入必要的信息,比如对象类型、对象标志、执行动作等。这些内容是由技术测试人员根据页面来输入的。如果不希望人工输入的话,那么也可以开发相应的工具去解析页面,来自动的生成每个页面的元素,或者是使用IBM Rational Functional Tester(简称RFT)的对象映射功能,由RFT去页面上抓取对象来生成。

    测试的动态结构和测试的要求有关。在创建测试用例的过程中,测试用例的每一个步骤,均是选自静态结构中的一个页面,将页面加入到测试用例中之后,还可以指定此次测试用例要测试页面上那些元素。另外,在测试的动态结构中,还可以指定测试数据、验证点、数据关联等操作。当设计完成后就直接生成真正可以被Robot测试技术框架所执行的表。

    以下是已经建好的动态结构的示例:


    图 5. 动态结构示例
    动态结构示例


    可以看到,左边是和按照测试的要求组织起来的测试用例。点开“票据托管”这个测试用例,可以在右边的上半部分看到此测试用例的执行步骤,比如第一步是“登录”,第二步是“票据托管导航”,依次下来是“票据托管”和“退出”,这些步骤都是从静态结构中选出来的。当点击测试步骤中“票据托管”这个页面,在下方将此页面的元素显示出来,业务测试人员可以为每一个测试元素输入数据、指定数据关联、添加验证点等。

    当业务测试人员设计好测试用例后,就可以将测试用例传递给Robot测试技术框架,又测试技术框架解释并执行。





    回页首


    4. 结论

    可以看到,使用IBM Rational Robot提供的强大功能所搭建起来的自动化功能测试框架,能够帮助软件开发组织成功的实施自动化的功能测试。

    1. 通过重用已有的静态结构和动态结构,能够有效的促进测试的重用,并且在IBM Rational Robot的支持下,可以自动的执行这些测试

    2. 通过使用测试设计工具来生成动态配置,可以看到除测试技术框架的SQABasic脚本外,不需要再维护任何其它的脚本,降低了脚本调试、维护的工作量。并且将来的维护是基于测试设计工具来进行,也降低了自动化测试整体的维护工作量

    3. 通过使用测试设计工具来生成静态配置,能够做到根据界面的设计来进行配置,而不需要等到待测试应用完全可用,就使得及早测试成为可能

    4. 通过支持业务、技术测试人员的分工,在测试技术框架中封装自动化测试技术细节,使得业务测试人员不需要自动化测试技术的相关知识,只需要通过测试设计工具,就能够简单、直观的进行测试的设计和执行,降低了自动化测试的实施难度


     

    另外,在实施自动化功能测试框架中,还发现两个有趣的现象。第一,因为可以去自动化的执行测试,所以业务测试人员更多的在使用测试设计工具,从而导致测试设计在整个测试中所占的比重有显著的提高,有效的提升测试的质量;第二,因为统一、一致的界面操作方式、提示方式和表达方式有利于自动化测试的进行,所以也间接的促使开发团队在设计、开发过程中更加注重界面的规范性以及界面控件的可测试性。

数据统计

  • 访问量: 8948
  • 日志数: 6
  • 建立时间: 2008-06-02
  • 更新时间: 2009-03-06

RSS订阅

Open Toolbar