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

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 中很容易实现。具备了这样一种通用的测试框架,您可以在将来的测试工程中大大地减少测试时间。


TAG: 自动化测试-功能测试

 

评分:0

我来说两句

日历

« 2024-05-04  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

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

RSS订阅

Open Toolbar