使用 Selenium 和 TestNG 进行编程式测试

上一篇 / 下一篇  2012-03-26 10:33:48 / 个人分类:Selenium

本文内容包括:
  使用 Selenium 进行编程式测试
  驱动应用程序
  Selenium 和 TestNG
 
  Create Widget 测试用例
51Testing软件测试网`\S,or$~(^ Y
  可重复的验收测试
  DbUnit 再次登场
  Cargo 执行加载
  结束语
51Testing软件测试网7r6a@8pt(h v'r
  参考资料
51Testing软件测试网.Y)a%Ei%UH mfi
  Selenium 是一种测试框架,它使您可在 Web 应用程序上轻松地运行用户验收测试(user acceptance test)。本月,Andrew Glover 将向您展示如何以编程的方式运行 Selenium 测试,并使用 TestNG 作为测试驱动程序。在将 TestNG 灵活的测试特性(包括参数化 fixture)添加到 Selenium 固有的工具包后,您需要做的就是借助 DbUnit 和 Cargo 的帮助编写完全自动化、逻辑可重复的验收测试。
 
  Selenium 是一种 Web 测试框架,它搭建了验证 Web 应用程序的新途径。与大多数尝试模拟 HTTP 请求的 Web 测试工具不同,Selenium 执行 Web 测试时,就仿佛它本身就是浏览器。当运行自动的 Selenium 测试时,该框架将启动一个浏览器,并通过测试中描述的步骤实际驱动浏览器,用户将使用这种方式与应用程序交互。
  由于开发人员和非开发人员都能够使用 Selenium 轻松地编写测试,使得它从众多测试框架应用程序中脱颖而出。在 Selenium 中,可以通过编程的方式编写测试,或者使用 Fit 样式的表,并且编写了测试后,可以使测试完全自动化。使用一个 Ant 构件(比方说)运行完整的 Selenium 套件非常简单,并且还可以在持续集成(Continuous Integration,CI)环境中运行 Selenium 测试。
 
  这个月,我将介绍 Selenium,并逐一查看使它成为优秀 Web 测试框架的一些特性 —— 尤其是在结合使用 TestNG、DbUnit 和 Cargo 这样的软件时。
  使用 Selenium 进行编程式测试
 
  在 Selenium 中,您可以使用自己喜爱的语言或者 Fit 样式的表通过编程来编写测试。从测试的角度来说,不管使用什么语言,测试过程和结果都不会有显著的差别。在此,我希望研究 Selenium 的编程方法,因为在结合使用 TestNG 时,它提供了一些有趣的可行方法能性。

6H*kM$aF-MrH0  使用具有类似 TestNG 这样的框架的 Selenium 进行编程式测试具有这样一个优点,它允许您创建智能 fixture,而使用 Fit 样式的表则很难做到这一点。TestNG 尤其适合与 Selenium 结合使用,因为它使您能够完成其他框架无法做到的测试,例如使用依赖项进行测试,重新运行失败了的测试,以及使用单独文件中定义的参数进行参数化测试。所有这些特性结合在一起,当然能够使它在众多 Web 应用程序测试框架中脱颖而出,但是,正如您将看到的,在完全自动化的验收测试中使用这些特性令它更加出众。
 
  配置第一个测试
  Selenium 架构实际上由两个逻辑实体组成:您编写的代码以及能够简化与测试中的应用程序的交互的 Selenium 服务器。要成功地执行测试,必须要启动并运行 Selenium 服务器实例以及要测试的应用程序。(当然,测试结果取决于您编写的应用程序是否优秀!)
  幸运的是,Selenium 服务器是一种轻量级程序,可以在实际的测试范围内通过编程启动和停止它。Selenium 服务器(使用 Selenium 对象嵌入)的启动和停止由一个 fixture 来执行。

u3pj6H2rt0  要通过编程的方式启动 Selenium 服务器,必须创建一个新的 Selenium 对象,并告诉它要使用哪一种兼容的浏览器 —— 我在下面的示例中使用的是 Firefox。您还必须提供运行服务器实例的位置(通常是 localhost,但不是必须的),以及被测试的应用程序使用的基 URL。

1z}5bv$[b^'C0  在清单 1 中,我配置了一个本地 Selenium 实例,使用它在本地安装的 Web 应用程序上驱动 Firefox(http://localhost:8080/gt15/)。正如您从参数中推断的一样,Selenium 是作为被测试的应用程序的代理,并相应地促进测试。
  清单 1. 配置 SeleniumServer
  Selenium driver =
  new DefaultSelenium("localhost", SeleniumServer.getDefaultPort(),

X |]*m R`&jk0  "*firefox", "http://localhost:8080/gt15/");
  driver.start();
  //go to web pages and do stuff...
 
  driver.stop();
  创建了 Selenium 实例后,您可以 启动并在运行时 停止它。这意味着您可以通过编程与 Selenium 服务器交互,并通过一个测试程序使它驱动浏览器。
  驱动应用程序
 
  通过编程与 Web 页面进行交互是一种使用本地 id 的应用。(一些读者可能对这种源自 本系列二月份关于 TestNG-Abbot 的文章 的概念比较熟悉)。与页面元素进行交互的第一步就是查找该元素,通常可以使用 HTML 元素 ID 进行查找。Selenium 还允许您使用 XPath、正则表达式,甚至是 JavaScript. 来查找特定的元素(如果您希望这样做)。
  清单 2 所示的 HTML 是使用 Groovlet 的简单 Web 应用程序的一部分。这段代码定义了包含输入和提交按钮的表单。如果希望 Selenium 与该表单交互,我必须为输入按钮提供 ID 以及相应的值。我还需要为提交按钮提供一个 ID,这样 Selenium 才能 “单击” 它。单击按钮后,表单将被提交给 Groovlet —— 本例中为 FindWidget.groovy。
  清单 2. 简单的 HTML 表单
 
  Widget:
 
  现在就可以通过使用 ID widget(输入值)和 submit(单击按钮)与该 HTML 表单进行编程式交互,如清单 3 所示:
51Testing软件测试网n2})O)U j
  清单 3. 驱动简单的 Web 页面
51Testing软件测试网3DpKsU#pO%U
  driver.type("widget", "pg98-01");
  driver.click("submit");
  driver.waitForPageToLoad("10000");
 
  //assert some return value...
  Selenium 中用于和 Web 页面元素进行交互的 API 非常的直观。对于输入字段,我可以使用 type() 方法将值与 ID 关联起来。如果需要的话,可以通过编程 click 按钮。在清单 3 中,我将 click 设置为 10 秒的等待时间 —— 足够表单提交请求完成处理。当 FindWidget.groovy 中的代码运行其内容并返回响应后,我可以使用该响应来查找特定页面元素,并验证所有内容是否正常工作

Z1s"eIkX^5T0Selenium 和 TestNG
  TestNG 以其灵活性和参数化 fixture 成为定义 Selenium 的驱动验收测试的首选。TestNG 能够定义测试依赖项并返回失败的测试,以及其易用性,使得 Selenium-TestNG 成为吸引人的组合。

w'A`EhHX}0  让我们首先从一个能够允许用户创建、查找、更新或删除小部件的 Web 应用程序开始。创建一个小部件需要三个属性:名称、类型和定义。图 1 显示了创建小部件的表单:
51Testing软件测试网1Vu~a;FPz1M
  图 1. 创建小部件的 Web 表单
 

H4N Q1A mdFglY0  请注意:表单元素的类型是具有三个不同选项的下拉列表,如图 2 所示:
  图 2. 包含下拉列表的 Web 表单
51Testing软件测试网6p*oF DE^%M{
  单击 Create Widget 将促使 Groovlet 处理这一请求。如果所有内容正确的话(即名字和定义不为空,并且数据库中不存在该实例),Groovlet 将创建一个新的小部件实例并类似图 3 所示的状态页面:
  图 3. 返回的 Web 页面显示状态
 

B*rI,p.`0  结合使用 Selenium 和 TestNG 验证简单的 Create Widget 用例是一种可管理的应用:
  配置并启动 Selenium 服务器的实例。
  与 Create Widget Web 表单交互并提交它。
  检验结果页面是否包含具有小部件名称的成功信息。
  停止 Selenium 服务器实例。
 
  请注意:用例中的每一步都是通过 Selenium 完成的 —— 所以说,TestNG 仅仅帮助进行查找。现在,我们来实践一下。
  Create Widget 测试用例
51Testing软件测试网W s:R xftJv5RAT
  我希望对 Selenium 服务器进行灵活的配置,所以我将编写一个参数化 fixture(TestNG-Selenium 样式),一般可以使用它来为不同浏览器、不同位置甚至混合的 Web 应用程序地址(类似 localhost 和产品)创建 Selenium 服务器。清单 4 定义了我所配置的灵活的 Selenium 服务器 fixture:
  清单 4. 灵活的 Selenium fixture
  @Parameters({"selen-svr-addr","brwsr-path","aut-addr"})
  @BeforeClass
 
  private void init(String selenSrvrAddr, String bpath,
 
  String appPath) throws Exception {

w&T!L V'@*r9v*O0  driver = new DefaultSelenium(selenSrvrAddr,

(yETK;Z/R$WC8M0  SeleniumServer.getDefaultPort(), bpath, appPath);
 
  driver.start();
  }

]p-wG cnBk0  //....
  @AfterClass
 
  private void stop() throws Exception {

4V+X+XU|w|(p0  driver.stop();
 
  }
 
  必须将参数名与 TestNG 的 testng.xml 文件中的值链接起来;因此,我定义了如清单 5 所示的三个参数。(默认情况下为 Firefox 定义了 brwsr-path 参数,但是我可以同样轻松地定义一组新的使用 Internet Explorer 的测试。)
  清单 5. TestNG testng.xml 文件中的参数值
  接下来,我将定义清单 6 所示的测试用例,它也包含一个参数,用于进行测试的应用程序的基 URL。该测试将促使浏览器在 Web 应用程序内打开特定页面,并操作 图 1 所示的表单。
51Testing软件测试网K1l UTMh [
  清单 6. 一个良好的测试用例
51Testing软件测试网#^a t? aWq9X7L+X
  @Parameters({"aut-addr"})
 
  @Test
  public void verifyCreate(String appPath) throws Exception {
  driver.open(appPath + "/CreateWidget.html");
 
  driver.type("widget", "book-01");

YX g W Z/[ wdh0  driver.select("type", "book");
 
  driver.type("definition", "book widget type book");
 
  driver.click("submit");

6B-NZ$Uz0  driver.waitForPageToLoad("10000");
  assertEquals(driver.getText("success"),
 
  "The widget book-01 was successfully created.",
51Testing软件测试网 m*I+dpW'R
  "test didn't return expected message");
  }
  通过调用 driver.click("submit") 提交表单后,Selenium 将等待响应的加载,然后我将断言成功的创建信息。(注意:响应 Web 页面具有一个 ID 为 success 的元素。)
  结果产生一个灵活的文本类,它将检验两种场景:一种是良好的场景,而另一种是没有提供定义的边界用例,如清单 7 所示:

-M"r#v0Z3`2V c4B#w0  清单 7. 使用 TestNG 进行全部的处理
  public class CreateWidgetUATest {
 
  private Selenium driver;

"EfQ!W)e C0  @Parameters({"selen-svr-addr","brwsr-path","aut-addr"})
  @BeforeClass
  private void init(String selenSrvrAddr, String bpath,
  String appPath) throws Exception {
  driver = new DefaultSelenium(selenSrvrAddr,
 
  SeleniumServer.getDefaultPort(), bpath, appPath);
  driver.start();
  }
  @Parameters({"aut-addr"})
 
  @Test
51Testing软件测试网C6e+isRE
  public void verifyCreate(String appPath) throws Exception {
 
  driver.open(appPath + "/CreateWidget.html");
  driver.type("widget", "book-01");
  driver.select("type", "book");
51Testing软件测试网Y[8Gr\
  driver.type("definition", "book widget type book");
  driver.click("submit");
51Testing软件测试网Y0N?7[o/F&t
driver.waitForPageToLoad("10000");
  assertEquals(driver.getText("success"),
 
  "The widget book-01 was successfully created.",
  "test didn't return expected message");
 
  }
51Testing软件测试网[ Q%M(v6K4@{{W,NFt
  @Parameters({"aut-addr"})
  @Test
 
  public void verifyCreationError(String appPath) throws Exception {
  driver.open(appPath + "/CreateWidget.html");
  driver.type("widget", "book-02");
  driver.select("type", "book");

!T+j.r)w7L&_ ^Q0  //definition explicitly set to blank
  driver.type("definition", "");
 
  driver.click("submit");
  driver.waitForPageToLoad("10000");
51Testing软件测试网6g^!fGmzxU
  assertEquals(driver.getText("failure"),

_,Q.e,S OxX0  "There was an error in creating the widget.",
  "test didn't return expected message");
  }
  @AfterClass

!^2zW8@VB{_0  private void stop() throws Exception {
 
  driver.stop();
51Testing软件测试网~lY;I|!bQ
  }
 
  }
 
  目前为止,我已经定义了两种足够灵活的 Selenium 测试,可以对多个浏览器进行测试,并且还可以对多个位置进行测试,这对初学者非常有利。尽管如此,我还想获得更高级点的应用,我开始考虑测试中的逻辑是否可重复使用。比如,如果对一行运行两次 CreateWidgetUATest 测试类会怎样?如何确保我的 Web 应用程序运行的是本地机器(或其他机器)上最新版本的代码?
  可重复的验收测试
  在执行 Selenium 测试时,必须运行 Selenium 服务器以及要检验的 Web 应用程序。言外之意,还必须运行应用程序中所有相关的架构依赖关系 —— 对于大多数 Java™ Web 应用程序来说,即 Servlet 容器和相关的数据库。
  正如在我的另一篇文章 repeatable system tests 中解释的一样,DbUnit 和 Cargo 是两种我最喜欢的技术,可以在依赖数据库的 Web 应用程序中实现逻辑重复。DbUnit 管理数据库中的数据,而 Cargo 使容器管理以通用的方式实现自动化。下面几节将向您展示如何结合使用 Selenium 和 TestNG 从而确保实现逻辑重复的验收测试。
 

TAG:

引用 删除 Fay冯   /   2019-12-16 16:06:57
5
 

评分:0

我来说两句

Open Toolbar