转载地址:

http://www.ibm.com/developerworks/cn/java/j-lo-junit-installanywhere/index.html

JUnit 简介

JUnit 是一个开源的单元测试框架,用于编写和运行自动测试,由 Erich Gamma 和 Kent Beck 在 1997 年开发完成。它包括以下特性:

  1. 提供的 API 可以让你写出测试结果明确的可重用单元测试用例;
  2. 提供了三种方式来显示你的测试结果,而且还可以扩展;
  3. 提供了单元测试用例成批运行的功能;
  4. 超轻量级而且使用简单,没有商业性的欺骗和无用的向导;
  5. 整个框架设计良好,易扩展。
 

InstallAnywhere 简介

InstallAnywhere(下文简称 IA)是一种多平台安装程序的开发工具,可用于将桌面系统、企业、或多模式 Web 服务等软件安装在任何平台上,并对这些应用程序进行配置,以获得最佳的性能。它包括以下特性:

  1. 支持多平台与多语言,可在任何客户端或服务器平台部署软件;
  2. 集成开发环境,简化安装开发与创造;
  3. 支持安装程序的个性化定制与优化;
  4. 实现软件部署的简化和标准化,降低测试与支持的成本。

由于安装程序自身的特点,对它进行自动测试一直是一个难题。对 IA 的前身 InstallShield 来说,一直没有好的方法将 JUnit 应用到安装程序的自动测试。IA 提供了这样的一个框架,使我们可以应用 JUnit 对安装程序进行自动测试,并且给我们留下对它进行扩展的可能性。本文就将对它进行剖析。

 

InstallAnywhere 安装程序图形界面自动测试框架结构

基于 Swing/AWT 的图形界面程序的自动测试对开发者来说一直是一个挑战,这是由于:

  • 底层图形框架的复杂性。
  • 应用的业务逻辑与图形界面相结合造成的复杂性。
  • 缺少直观的自动测试框架。

对基于 InstallAnywhere 开发的安装程序界面进行自动测试同样面临这些问题。前两个情况是一直都存在的,本文重点研究第三种情况。设计一个安装程序界面自动测试框架需要解决以下问题:

  1. 自动跟踪测试每一个窗口和面板。
  2. 自动测试每个面板上的控件,如文本框、下拉列表、按钮等。

IA 提供了一个基于 JUnit 3 的安装程序界面自动测试框架,基于它我们可以方便的编写测试程序对安装程序界面进行自动单元测试。IA 图形界面自动测试框架提供了 4 种 fixture:工作目录 fixture、临时目录 fixture、JAVA 程序执行 fixture,和界面自动测试 fixture。工作目录和临时目录 fixture 分别用于创建工作目录和临时目录。JAVA 程序执行 fixture 用于执行使用 IA 开发的安装程序。

图形界面自动测试 fixture 是整个架构的核心,下面将对它进行详细介绍。


图 1. IA 图形界面自动测试框架架构图
图 1. IA 图形界面自动测试框架架构图 

如图 1 所示界面自动测试 Fixture 由测试用例控制器,事件通知服务器和自测试机器人组成。测试用例控制器定义并控制测试用例。测试用例包括要测试的窗口和面板序列,以及系统输入事件用来测试面板上每个控件。事件通知服务器监听安装程序窗口激活(windows.active)和面板显示 (panel.show) 事件。自测试机器人产生系统输入,如按键,点击鼠标等。

测试开始时,此测试框架先创建事件通知服务器。事件通知服务器是一个 socket 服务器,它监听来自 IA 安装程序的事件,IA 安装程序启动一个窗口以及显示一个面板都会向事件通知服务器发送一个事件通知。然后 JAVA 程序执行 fixture 启动 IA 安装程序。接下来,测试用例控制器会根据事先定义好的测试用例按照线性顺序接收来自 IA 安装程序的事件和向 IA 安装程序发送系统输入,直到所有测试完成。

在下一节,本文将举例说明如何使用 IA 安装程序图形界面自动测试框架。

 

举例说明如何使用 IA 安装程序图形界面自动测试框架

本文用一个使用 IA 开发的安装程序演示如何使用本文介绍的测试框架。此安装程序包括三个面板 :Introduction, Choose Install Folders 和 Install Complete(图 2-4),安装程序会创建用户指定的安装路径,并将一个文件复制到安装路径。测试内容包括:窗口是否被成功打开,面板是否被成功显示,安装程序是否正确响应了系统事件,如点击按钮,输入字母等。


图 2. 面板 Introduction
图 2. 面板 Introduction 

图 3. 面板 Choose Install Folders
图 3. 面板 Choose Install Folders 

图 4. 面板 Install Complete
图 4. 面板 Install Complete 

应用本文介绍的框架,对它进行自动化单元测试变得很简单。要使用 IA 提供的测试框架,要把 IA 的自动测试库文件 ia-gui-test-auto.jar 加入到 CLASSPATH 中,你可以在 $IAHOME$ \gui-test-auto\lib 中找到它。接下来编写测试程序,首先你要继承 GUIAutomationFixture 编写自己的测试程序,GUIAutomationFixture 实现了上一节所讲的图形界面自动测试 fixture。

public class BasicProjectAutomation extends GUIAutomationFixture 

然后你要编写测试方法,测试方法要做下面三件事情:

  1. 指定执行的安装程序;
  2. 执行测试用例;
  3. 设置断言,检查程序安装是否成功。

清单 1. 编写测试方法
				
1)  String NEW_LOCATION = "newlocation";
2)  String productName = "BasicProject";
3)  String buildOutput = "_Build_Output/Web_Installers/InstData/Java";
4)  File installer = new File("./" + productName + buildOutput, "install.jar");
5)  File installDir = new File("C:/Program Files",NEW_LOCATION);
6)
7)  setWaitTimeout(30 * SECONDS);
8)
9)  runInstall(productName, installer);
10) assertInstallerHasCompletedSuccessfully();
11) assertTrue("Install dir should have been created.", installDir.exists());
12) assertTrue("file-to-install.txt", new File(installDir, 
        "file-to-install.txt").exists());
			

清单 1 中第 2-5 行指定要执行的安装程序,第 9 行执行测试用例,第 10-12 行设置断言,检查程序安装是否成功。第 10 行检查安装程序是否正常退出,第 11 行检查安装目录是否创建成功,第 12 行检查 file-to-install.txt 是否被复制到安装目录中。

测试用例定义了要测试的面板以及发送给安装程序的系统事件,如以下清单 2 所示。


清单 2. 编写测试用例
				
1)  private void runInstall(String productName, File installer) {
2)    try {
3)        launchInstaller(installer.getPath());
4)        
5)        waitForWindow(productName);
6)        waitForPanel("Introduction");
7)        pressEnter();
8)
9)        waitForPanel("Choose Install Folder");
10)        pressTab();
11)        for (int i = 0; i < productName.length(); i++) {
12)            pressKey(KeyEvent.VK_BACK_SPACE);
13)        }
14)        type(NEW_LOCATION);
15)        waitForPanel("Install Complete");
16)        pressEnter();
17)
18)        waitForInstallerToComplete();
19)    } finally {
20)        printJavaOutput("Installer");
21)    }
22) }
			

清单 2 中第 3 行启动待测试的安装程序。清单 2 中 waitForWindow 及 waitForPanel 方法从事件通知服务器中获取从安装程序传来的事件,其中窗口事件定义为 window.activated:WINDOWS_NAME,面板显示事件定义为:panel.shown:PANEL_NAME 如果在预定的事件内没有接收到相应的事件,就抛出异常退出程序。清单 2 中 pressTab, pressKey,type press 及 Enter 方法通知自测试机器人向安装程序发送按键及点击鼠标等系统事件。例如清单 2 中第 10-14 行修改了 Choose Install Folders 面板中的安装路径。

 

对 IA 安装程序图形界面自动测试框架的扩展

IA 提供的图形界面自动测试框架也存在以下不足:

  1. 不能对用户自定义的面板进行测试;
  2. 不能对用户自定义的业务逻辑进行测试;
  3. 由于测试案例采用 java 程序编写,此框架不适合用于测试复杂的安装程序。

基于 IA 提供的框架,本文通过扩展事件通知服务器所接收的事件类型来实现对用户自定义的面板和业务逻辑的测试。并且定义了 XML 格式的测试脚本,用来编写复杂的测试案例,这样开发者可以集中注意力在测试案例的编写上,不用考虑 Java 语法问题,这样就解决了第三个问题。

首先说明如何通过扩展事件通知服务器所接收的事件类型来实现对用户自定义的面板和业务逻辑的测试。用户自定义的面板显示事件定义为 cuspanel.shown:PANEL_NAME,用户自定义的业务逻辑事件定义为 cuscode:active:CUSCODE_NAME。代码如以下清单 3 所示。


清单 3. 扩展事件通知服务器
				
1)  protected void waitForCusPanel(String s)
2)  {
3)      waitForEvent("cuspanel.shown:" + s);
4)  }
5)
6)  protected void waitForCusCode(String s)
7)  {
8)      waitForEvent("cuscode:active:" + s);
9)  }
			

在用户自定义的面板和业务逻辑要向事件通知服务器发送相应的事件,如以下清单 4 为用户自定义的面板向事件通知服务器发送面板显示事件。


清单 4. 用户自定义的面板向事件通知服务器发送面板显示事件
				
1)  Socket connectToServer=new Socket(server,12060);
2)  OutputStreamWriter ow = new OutputStreamWriter(connectToServer.getOutputStream());
3)  ow.write("panel.shown:TestCustomerCodePanel");
4)  ow.flush();
5)  ow.close();
6)  connectToServer.close();
			

接下来说明如何采用 XML 格式的测试脚本描述测试案例,并且改进测试案例控制器去解析并自动执行测试脚本。扩展后的 IA 安装程序图形界面自动测试框架如下图所示:


图 5. 扩展后的 IA 安装程序图形界面自动测试框架架构图
图 5. 扩展后的 IA 安装程序图形界面自动测试框架架构图 

描述测试案例的 XML 文档结构如下表所示。


表 1. 测试案例脚本的文档结构
节点 子节点 属性
Product install,uninstall installer
Path
Install presenter, pressTab, type, 
pressKey, releaseKey, 
waitForWindow, 
waitForPanel, 
waitForCusPanel, 
waitForCusCode, 
launchInstaller, 
waitForInstallerToComplete
 
Uninstall presenter, pressTab, type, 
pressKey, releaseKey, 
waitForWindow, 
waitForPanel, 
waitForCusPanel, 
waitForCusCode, 
launchUninstaller, 
waitForInstallerToComplete 
 
pressEnter    
pressTab   times
type    
pressKey   times
releaseKey    
waitForWindow    
waitForPanel    
waitForCusPanel    
waitForCusCode    
launchInstaller    
launchUninstaller   name
waitForInstallerToComplete    

清单 2 中所示的测试案例可以用以下清单 5 中的测试案例脚本代替:


清单 5. 测试案例脚本
				
1)  <?xml version="1.0" encoding="UTF-8"?>
2)  <Product name="BasicProject" installer="install.jar"
3)      buildOutput="_Build_Output/Web_Installers/InstData/Java">
4)      <install>
5)        <waitForWindow>BasicProject</waitForWindow>
6)        <waitForPanel>Introduction</waitForPanel>
7)        <pressEnter></pressEnter>
8)        <waitForPanel>Choose Install Folder</waitForPanel>
9)        <pressTab times="1"></pressTab>
10)       <pressKey times="12"></pressKey>
11)       <type>newlocation</type>
12)       <waitForPanel>Install Complete</waitForPanel>
13)       <pressEnter></pressEnter>
14)       <waitForInstallerToComplete></waitForInstallerToComplete>
15)     </install>
16)  </Product>
			

 

总结

本文介绍了 InstallAnyWhere 提供的基于 JUnit 安装程序图形界面自动测试框架,对它进行了深入的剖析,并举例说明如何应用它。更进一步分析了它的不足,并针对这些不足对它进行进一步的扩展,使它更完善和使用于复杂的安装程序的自动测试。使之成为将测试驱动开发模式应用到 InstallAnyWhere 开发的基础。


参考资料

学习

讨论