使用 Selenium Grid 改进 Web 应用程序的测试

在多种环境中运行自动化并行测试

Selenium 是专门设计来在许多平台上实现 Web 应用程序测试自动化的工具套件。通过套件中的 Selenium Grid,您可以将您的测试透明地分发到多个主机上。在本文中,您将了解如何并行地执行测试,减少运行浏览器测试套件所需要的时间。通过真实的测试项目和代码示例, 学习如何在多个环境中并行地执行测试和加快 Web 应用程序的测试速度。

Zhen Li, 软件工程师, IBM

/developerworks/i/p-lzhen.jpgLi Zhen 是 IBM 中国开发实验室 datapower 管理部门的一位软件工程师。她目前专注于 Web 应用程序测试工具和测试自动化。



Yong Hu Sun, 软件工程师, IBM

/developerworks/i/p-shu.jpgSun Yong Hu 是 IBM 中国开发实验室 datapower 管理部门的一位软件工程师,而且是 WebSphere Application Management Center SVT 团队的主管。他目前主要关注于敏捷系统验证测试和测试自动化。



2012 年 6 月 20 日

简介

Selenium Remote Control (RC) 是 Selenium 项目工具套件的一个部分,它是一个自动化的 Web 应用程序测试框架。Selenium RC 支持许多的编程语言和几乎所有的浏览器。Selenium RC 最重要的优势是浏览器的驱动方法。与其他 Web UI 自动化工具不同,Selenium RC 是通过 JavaScript 来驱动浏览器的,所以测试不会被鼠标事件中断。测试人员可以在测试运行时执行其他任务。

Selenium Grid 通过在不同服务器上并行执行测试来扩展 Selenium RC。它能够减少时间,从而减少在多个操作系统的不同浏览器上进行测试的开支。

Selenium 工具套件是一些只有少量正式文档和指南的开源项目,所以学习曲线可能比较曲折一些。在本文中,您将了解用 Java 编写的 Selenium Grid (Version 1.0.6) 测试,以及运行 TestNG 测试框架的方式。

Selenium Grid

Selenium Grid 有两个组件:Selenium Hub 和 Remote Control。中心会接收测试的请求(与 Selenium RC 相同),然后为每一个测试分配中心所注册的远程控制信息,如 图 1 所示:

图 1. Selenium Hub 和 Selenium RC 在 Selenium Grid 中的关系
表示组件的框图是用双向箭头连接的;测试脚本与 Selenium Hub 相连,而它又会与两个不同的 Selenium RC 连接,它们又分别连接自己的浏览器,再连接到 Web 应用程序

测试人员不需要修改代码就可以在 Selenium Grid 中执行测试。整个过程是透明的;测试人员不需要知道或关心实际的基础架构。

如果您熟悉 Selenium RC,那么您将能够很容易使用 Selenium Grid 来执行测试。您还可以在多台主机上并行地执行现有代码,这能够节省测试执行时间和快速生成测试结果反馈。然而,Selenium Grid 本身并不提供并行的执行策略。如果您希望利用 Selenium Grid 的优势,那么您需要编写以并行模式运行的 Selenium 测试。


准备使用 Selenium Grid

要开始使用 Selenium Grid,您首先需要下载和安装它(见 参考资料 的链接)。Selenium Grid 是一个包含 JAR 库文件、示例文件、Ant 编译文件和其他文件的文件夹。要在 Selenium Grid 中执行测试,您需要有:

  • Ant 1.7 或以上版本,用于编译、汇编、测试和运行 Java 应用程序(在编译文件中的目标和扩展点中描述)。
  • JDK 5+。
  • Selenium RC 基础知识,因为 Selenium Grid 是基于 Selenium RC 的。(见 参考资料 中关于 Selenium RC 的信息)。测试人员应该知道如何使用 Selenium RC 编写和执行测试。

本文的例子分别使用 Java 技术和 TestNG 作为编程语言和测试框架。TestNG 是专门用来简化广大测试需求和扩展 JUnit 的。(见 参考资料 中更多关于 TestNG 的信息。)清单 1 显示的是一个简单的 TestNG 配置文件。

清单 1. 简单的 TestNG 配置文件
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite1"  parallel="methods" thread-count="2">
<test name="Testcase20" >
        <classes>
            <class name="com.test.workflow.device.testcase20"/>
        </classes>
  </test>
</suite>

<suite> 标签可以表示一个包含一个或多个测试的 TestNG XML 文件。<test> 标签支持在测试中加入一个或多个 TestNG 类。<class> 标签表示一个 TestNG 类可以包含一个或多个测试方法。(见 参考资料 关于标签的更详细信息。)测试方法是在 Java 文件中定义的,如 清单 2 所示:

清单 2. 在 Java 文件中定义的测试方法
@Test
public void testMethod()
{
    ....
}

测试人员使用 Java 编程语言和测试框架来编写测试脚本,然后使用 Ant 在命令行中运行 TestNG 类。下面让我们看看使用 Ant 来运行 TestNG 的整个过程。

  1. 在命令行中运行 ant(目标名) [编译文件名]
  2. Ant 会读取 build.xml 文件获取项目参数,导入文件、类路径定义、目标定义等。
  3. Ant 会将 Java 源代码编译为 TestNG 类。
  4. Ant 关注于所运行的目标和获取目标配置。
  5. 读取 TestNG 配置文件获取参数、测试类名等。
  6. 按照 TestNG 配置文件来运行 TestNG 类。

示例测试用例

本文关注于如何使用整合 TestNG 和 Ant 的 Selenium Grid 来并行地执行测试,所以我们将使用一个基于 PHP 页面的示例应用程序。所设计的测试用例旨在简单地单击页面的标签。图 2 显示了示例应用程序网页。

图 2. 应用程序网页的组成部分
屏幕截图显示的是应用程序的网页,它包含以下标签:Test Case、View Time、Run Scripts、Long Run、LA、s-Cat、Jmeter

清单 3 包含这些标签的示例源代码。

清单 3. 标签的源代码
<div class="Tabs" style="width: 100%;">
  <a class="Current">Test Case</a>
  <a>View Time</a>
  <a>Run Scripts</a>
  <a>Long Run</a>
  <a>LA</a>
  <a>s-CAT</a>
  <a>Jmeter</a>
</div>

测试机需要进行以下准备。

IP操作系统类型
9.181.138.75win2003
9.181.138.186win2003
9.181.128.184 Linux

将 test 文件夹移动到 selenium-grid-1.0.6 目录下,这个文件夹的内容如 图 3 所示。

图 3. 测试用例文件夹内容
屏幕截图显示了测试用例文件夹内容,其中包括子文件夹 src 和 目标,build.xml 和 testing.xml 文件

src 目录包含了 Java 源代码文件。target 目录包含了所有编译后类文件和报告文件。如 清单 4 所示的 build.xml 文件是一个 Ant 编译文件,它定义了目标配置。它包含调用的 TestNG 配置文件、项目参数和 lib 文件路径等。testng.xml 文件是示例测试用例的 TestNG 配置文件。

清单 4. build.xml
<project name="Selenium Grid Test" default="run" basedir=".">
  <description>Selenium Grid Test</description>
  <property name="rootdir" value="${basedir}/.."/>
  <property file="${rootdir}/project.properties"/>
  <property name="name" value="Selenium Grid Demo"/>
  <property name="artifact" value="selenium-grid-demo"/>
  <property name="version" value="SNAPSHOT"/>
  <property name="selenium.version" value="SET ME"/>
  <property name="build.src" location="src"/>

  <import file="${rootdir}/lib/build/common-build.xml" />

  <path id="compile.classpath">
    <fileset dir="${rootdir}/vendor">
      <include name="selenium-java-client-driver-${selenium.version}.jar"/>
      <include name="testng-5.7-jdk15.jar"/>
      <include name="commons-logging-1.0.4.jar"/>
    </fileset>
    <pathelement location="${rootdir}/tools/target/classes"/>
    <pathelement location=
    "${rootdir}/tools/target/dist/lib/selenium-grid-tools-standalone-${version}.jar"/>
    <pathelement location="${rootdir}/lib/selenium-grid-tools-standalone-${version}.jar"/>
    <pathelement path="${java.class.path}/"/>
  </path>

  <path id="runtime.classpath">
    <path refid="compile.classpath"/>
    <pathelement path="${build.output}/"/>
  </path>

  <target name="run" depends="compile" description="test">
       <java classpathref="runtime.classpath"
        classname="org.testng.TestNG"
        failonerror="true">
      <sysproperty key="java.security.policy" file="${rootdir}/lib/testng.policy"/>
      <arg value="-d" />
      <arg value="${basedir}/target/reports" />
      <arg value="-suitename" />
      <arg value="suite1" />
      <arg value="testng.xml"/>
    </java>

  </target>

  <target name="build" depends="compile"/>
  <target name="dist" depends="build"/>
  <target name="coverage-analysis" />
  
</project>

运行示例测试用例

现在我们已经建立了环境和测试数据,您可以执行并行测试的三个不同的场景:

在一台服务器的不同浏览器上执行相同的测试用例

要在一台服务器的不同浏览器上执行相同的测试用例,您需要进入 Selenium Grid 的安装目录:

ant launch-hub

在同一台主机的新窗口中,或者在另一台主机上,输入:

ant launch-remote-control
ant Denvironment=*iehta launch-remote-control

ant  -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control
ant  -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 
       -Denvironment=*iehta launch-remote-control

在一个浏览器上,转到中心的控制台:http://localhost:4444/console。现在您应该会看到页面列出了两个远程控制,如 图 5 所示。

图 4. Selenium Grid Hub 控制台
Selenium Grid Hub 控制台的屏幕截图显示了两个可用的远程控制

将 清单 5 所示的测试用例源代码放到 src 目录。

清单 5. 测试用例的 Java 源代码
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import org.testng.annotations.Parameters;

public class GridTest2 {
	String url = "http://9.181.138.186/index.php";
	private Selenium selenium= null;

	@Parameters({ "bs" })
	@BeforeClass
	public void startBroswer(String broswer) 
	{
		selenium= new DefaultSelenium("localhost", 4444, broswer, url);
		selenium.start();
		selenium.open(url);
		selenium.windowMaximize();
	
	}
	@Test
	public void test() throws InterruptedException
	{
		selenium.click("xpath=//a[contains(text(),\'LA\')]");
		Thread.sleep(10000);
	}
	@AfterClass
	public void clear() {
		selenium.stop();
	}	
}

修改 testing.xml 的内容,如 清单 6 所示:

清单 6. TestNG 配置文件内容
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1"  annotations="JDK" parallel="tests" thread-count="2">   
  <test name="test1">
	<parameter name="bs"  value="*firefox"/>
    <classes>
      <class name="GridTest2" />
    </classes>
 </test>
 <test name="test2">
	<parameter name="bs"  value="*iehta"/>
    <classes>
      <class name="GridTest2" />
    </classes>
 </test>
</suite>

testng.xml 文件的 bs 参数定义了 test1 运行在 Firefox 浏览器,而 test2 运行在 Internet Explorer 上。parallel 属性定义了测试要并行运行。thread-count 属性定义了所运行的线程数。这里只定义了两个测试,所以这两个测试会同时运行。

打开一个窗口,然后转到 test 目录:

ant run

这个测试用例将会自动运行。

在不同服务器的不同浏览器上执行不同的测试用例

要在不同服务器的不同浏览器上执行不同的测试用例,您需要转到 Selenium Grid 安装目录:

ant launch-hub

在同一台主机的一个新窗口中,或者在另一台主机的一个窗口中,输入:

ant launch-remote-control
ant Dport=6666 Denvironment=*iehta launch-remote-control

在主机 9.181.138.186 的一个窗口中,输入:

ant  -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control

在主机 9.181.138.184 的一个窗口中,输入:

ant  -Dhost=9.181.138.184 DhubURL=http://9.181.138.75:4444 launch-remote-control

在一个浏览器上,转到中心控制台:http://localhost:4444/console。您现在应该能够看到页面列出了 4 个远程控制。它应该类似于 图 5。

图 5. Selenium Grid Hub 控制台
Selenium Grid Hub 控制台的屏幕截图,显示了 4 个可用的远程控制

将 清单 7 中的测试用例源代码放到 src 目录中。

清单 7. 测试用例的 Java 源代码
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class GridTest2(3/4) {
	String url = "http://9.181.138.186/index.php";
	private Selenium selenium= null;

	@Parameters({ "bs" })
	@BeforeClass
	public void startBroswer() 
	{
selenium= new DefaultSelenium("localhost", 4444, broswer, url);
		selenium.start();
		selenium.open(url);
		selenium.windowMaximize();
	
	}
	@Test
	public void test() throws InterruptedException
	{
		selenium.click("xpath=//a[contains(text(),\'View Time\')]");
		//any code is ok
		Thread.sleep(10000);
	}
	@AfterClass
	public void clear() {
		selenium.stop();
	}
}

修改 testing.xml 文件的内容,如 清单 8 所示:

清单 8. TestNG 配置文件内容
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1"  annotations="JDK" parallel="tests" thread-count="2" >   
  <test name="test2"  junit="false" >
    <parameter name="bs"  value="*iehta"/>
    <classes>
      <class name="GridTest2" />
    </classes>
 </test>
 <test name="test3"  junit="false">
    <parameter name="bs"  value="*firefox"/>
    <classes>
      <class name="GridTest3" />
    </classes>
 </test>
<test name="test4"  junit="false">
    <parameter name="bs"  value="*firefox"/>
    <classes>
      <class name="GridTest4" />
    </classes>
 </test>
</suite>

只有两个测试用例可以同时执行,因为这里只定义了两个线程。虽然远程控制有 4 个,但是中心将会选择 RC1 来运行 GridTest2,而其余 2 个远程控制会运行 GridTest3 和 GridTest4。这两个测试的并行运行是随机的。图 6 显示了中心的运行状态。

图 6. Selenium Grid Hub 控制台
Selenium Grid Hub 控制台屏幕截图显示了两个可用的远程控制和两个激活的远程控制

如果您希望一次运行全部 3 个测试,那么只需要将 thread-count 修改为 3。

在不同服务器的相同浏览器上并行地执行不同的测试用例

要在不同服务器的相同浏览器上并行地执行不同的测试用例,您需要转到 Selenium Grid 安装目录:

ant launch-hub

在主机 9.181.138.186 中打开一个新窗口,然后输入:

ant  -Dhost=9.181.138.186 DhubURL=http://9.181.138.75:4444 launch-remote-control

在主机 9.181.138.184 的一个窗口中,输入:

ant  -Dhost=9.181.138.184 DhubURL=http://9.181.138.75:4444 launch-remote-control

在一个浏览器中,转到中心控制台:http://localhost:4444/console。现在您应该看到页面列出了 3 个或 4 个远程控制。将 清单 9 的测试用例源代码放到 src 目录中。

清单 9. 测试用例的 Java 源代码
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import static com.thoughtworks.selenium.grid.tools.
    ThreadSafeSeleniumSessionStorage.closeSeleniumSession;
import static com.thoughtworks.selenium.grid.tools.
    ThreadSafeSeleniumSessionStorage.session;
import static com.thoughtworks.selenium.grid.tools.
    ThreadSafeSeleniumSessionStorage.startSeleniumSession;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;

public class GridTest {
	String url = "http://9.181.138.186/index.php";
	private Selenium selenium;  

    	@BeforeMethod(alwaysRun = true)
    	protected void startSession() {
        		startSeleniumSession("localhost", 4444, "*firefox", url);
        		selenium = session(); 
  		selenium.open("/");
   	  	selenium.windowMaximize();
    	}

   	 @AfterMethod(alwaysRun = true)
    	protected void closeSession() {
        		closeSeleniumSession();
    	}
	@Test
	public void test() throws InterruptedException
	{
		
		selenium.click("xpath=//a[contains(text(),\'View Time\')]");
		Thread.sleep(10000);
	}
	@Test
	public void test2() throws InterruptedException
	{
		selenium.click("xpath=//a[contains(text(),\'LA\')]");
		Thread.sleep(10000);
	}
	@Test
	public void test3() throws InterruptedException
	{
		selenium.click("xpath=//a[contains(text(),\'Test Case\')]");
		Thread.sleep(10000);
	}	
}

修改 testing.xml 文件的内容,如 清单 10 所示。

这个源代码与常见的 Selenium RC 脚本是很不同的。它将一个 Selenium 对象初始化为一个会话对象,因为这些方法是必须单独运行的,所以 Selenium 应该在方法执行前启动会话,在方法执行后关闭会话。

清单 10. TestNG 配置文件内容
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="suite1" verbose="1"  parallel="methods" thread-count="2">   
  <test name="test"  junit="false">
    <classes>
      <class name="GridTest" />
    </classes>
 </test>
</suite>

parallel 属性会修改为 methods,这意味着类中的这些方法会并行运行。这些类是按顺序执行的。


查看测试结果

查看测试结果是很容易的。转到 build.xml 文件定义的 target 文件夹,然后转到 reports 文件夹。打开 index.html,然后单击 suite name 链接。您应该看到测试结果,如 图 7 所示,这是第 3 个例子的测试结果。

图 7. 测试结果
测试结果屏幕截图,其中有一个表格显示通过/失败/忽略的测试数、测试开始的日期、总时间、包含的组和排除的组,另一个表格详细记录测试方法和测试通过的时间(秒为单位)

更详细的信息,单击左边的 chronological 链接。您可以查看详细的信息,如 图 8 所示:

图 8. 详细的测试结果
包含详细测试结果的表格截图:时间、增量、套件配置、测试配置、类配置、组配置、方法配置、测试方法、线程和实例

结束语

在本文中,您了解了如何使用 Selenium Grid 来并行地运行 Selenium 测试。使用 Selenium Grid 执行自动化的 Web 应用程序测试能够节省大量的时间,并且能够节约资源。例如,如第二个场景中所描述的,如果一位测试人员有 100 个测试用例,配置了 10 个线程来执行测试用例,那么它就能够节省 10 倍的时间和人力。当然,远程控制的数量也是有限的。

并行测试也使回归测试变得更方便。希望您能够利用本文所介绍的方法,有效地加快您的 Web 应用程序测试。

参考资料

学习

  • SeleniumHQ:了解所有关于使用 Selenium 工具套件在多个平台上自动化 Web 应用程序测试的方法。
  • Selenium 和 Selenium RC 的文档:这个用户指南介绍了 Selenium,讲解了它的特性,并展示了 Selenium 社区中通常使用的最佳实践方法。
  • Selenium Grid:了解 Selenium Grid 如何能够将您的测试分布在多台主机上,这样您就能够并行地执行测试。
  • TestNG:更多地了解 TestNG 以及如何定义 TestNG Ant 任务。
  • Apache Ant:阅读所有关于 Apache Ant 项目的信息。
  • 查看 HTML5 专题,了解更多和 HTML5 相关的知识和动向。

获得产品和技术

  • Selenium Grid:下载 Selenium Grid。
  • TestNG:获取 TestNG,它是一个灵活的测试框架,也可用于驱动 Selenium 测试。
  • Apache Ant:获取 Apache Ant,它是一个 Java 库和命令行工具,将 build 文件中描述的过程作为相互关联的目标和扩展点。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development
ArticleID=821967
ArticleTitle=使用 Selenium Grid 改进 Web 应用程序的测试
publish-date=06202012