首页 测试 工具 查看内容

追求代码质量: 使用 Selenium 和 TestNG 进行编程式测试

2014-8-5 23:26| 发布者: tianzc| 查看: 737| 评论: 0

摘要: Selenium 是一种测试框架,它使您可在 Web 应用程序上轻松地运行用户验收测试(user acceptance test)。本月,Andrew Glover 将向您展示如何以编程的方式运行 Selenium 测试,并使用 TestNG 作为测试驱动程序。在将 ...

        结合使用 Selenium 和 TestNG 验证简单的 Create Widget 用例是一种可管理的应用

        配置并启动 Selenium 服务器的实例。
        与 Create Widget Web 表单交互并提交它。
        检验结果页面是否包含具有小部件名称的成功信息。
        停止 Selenium 服务器实例。
        请注意:用例中的每一步都是通过 Selenium 完成的 —— 所以说,TestNG 仅仅帮助进行查找。现在,我们来实践一下。

Create Widget 测试用例

        我希望对 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 {
  driver = new DefaultSelenium(selenSrvrAddr,
    SeleniumServer.getDefaultPort(), bpath, appPath);
  driver.start();
 }
 //....
 @AfterClass
 private void stop() throws Exception {
  driver.stop();
 }
 


        必须将参数名与 TestNG 的 testng.xml 文件中的值链接起来;因此,我定义了如清单 5 所示的三个参数。(默认情况下为 Firefox 定义了 brwsr-path 参数,但是我可以同样轻松地定义一组新的使用 Internet Explorer 的测试。)


清单 5. TestNG testng.xml 文件中的参数值
               
 <parameter name="selen-svr-addr" value="localhost"/>
 <parameter name="aut-addr" value="http://localhost:8080/gt15/"/>
 <parameter name="brwsr-path" value="*firefox"/>
 


        接下来,我将定义清单 6 所示的测试用例,它也包含一个参数,用于进行测试的应用程序的基 URL。该测试将促使浏览器在 Web 应用程序内打开特定页面,并操作 图 1 所示的表单。


清单 6. 一个良好的测试用例
               
 @Parameters({"aut-addr"})
 @Test
 public void verifyCreate(String appPath) throws Exception {
  driver.open(appPath + "/CreateWidget.html");
  driver.type("widget", "book-01");
  driver.select("type", "book");
  driver.type("definition", "book widget type book");
  driver.click("submit");

  driver.waitForPageToLoad("10000");  
  assertEquals(driver.getText("success"),
    "The widget book-01 was successfully created.",
    "test didn't return expected message");
 }
 


        通过调用 driver.click("submit") 提交表单后,Selenium 将等待响应的加载,然后我将断言成功的创建信息。(注意:响应 Web 页面具有一个 ID 为 success 的元素。)

        结果产生一个灵活的文本类,它将检验两种场景:一种是良好的场景,而另一种是没有提供定义的边界用例,如清单 7 所示:


清单 7. 使用 TestNG 进行全部的处理
               
public class CreateWidgetUATest {
 private Selenium driver;

 @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
 public void verifyCreate(String appPath) throws Exception {
  driver.open(appPath + "/CreateWidget.html");
  driver.type("widget", "book-01");
  driver.select("type", "book");
  driver.type("definition", "book widget type book");
  driver.click("submit");

  driver.waitForPageToLoad("10000");  
  assertEquals(driver.getText("success"),
    "The widget book-01 was successfully created.",
    "test didn't return expected message");
 }

 @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");
  //definition explicitly set to blank
  driver.type("definition", "");
  driver.click("submit");

  driver.waitForPageToLoad("10000");  
  assertEquals(driver.getText("failure"),
    "There was an error in creating the widget.",
    "test didn't return expected message");
 }

 @AfterClass
 private void stop() throws Exception {
  driver.stop();
 }
}
 


        目前为止,我已经定义了两种足够灵活的 Selenium 测试,可以对多个浏览器进行测试,并且还可以对多个位置进行测试,这对初学者非常有利。尽管如此,我还想获得更高级点的应用,我开始考虑测试中的逻辑是否可重复使用。比如,如果对一行运行两次 CreateWidgetUATest 测试类会怎样?如何确保我的 Web 应用程序运行的是本地机器(或其他机器)上最新版本的代码?

可重复的验收测试

        在执行 Selenium 测试时,必须运行 Selenium 服务器以及要检验的 Web 应用程序。言外之意,还必须运行应用程序中所有相关的架构依赖关系 —— 对于大多数 Java™ Web 应用程序来说,即 Servlet 容器和相关的数据库。

        正如在我的另一篇文章 repeatable system tests 中解释的一样,DbUnit 和 Cargo 是两种我最喜欢的技术,可以在依赖数据库的 Web 应用程序中实现逻辑重复。DbUnit 管理数据库中的数据,而 Cargo 使容器管理以通用的方式实现自动化。下面几节将向您展示如何结合使用 Selenium 和 TestNG 从而确保实现逻辑重复的验收测试。

DbUnit 再次登场

        您可能回想起,DbUnit 通过有效地管理测试场景中的数据简化了使用数据库的工作。通过使用 DbUnit,可以在测试前将一组已知的数据加载到数据库中,这意味着您可以依赖这些在测试过程中呈现的数据。此外,在完成测试后,还可以从数据库中删除测试结果产生的数据。DbUnit 作为一种方便的 fixture(JUnit 或 TestNG)简化了所有这些工作,它能够读取包含测试数据的种子文件,逻辑插入、删除数据,或更新数据到相应的数据库表中。

        由于这里使用了 TestNG 驱动 Selenium,我将创建一个 DbUnit fixture,它将在测试 级别上运行。TestNG 支持在五种粒度级别上运行 fixture。最低的两种级别,方法和类是最常见的 —— 用于每个测试方法的 fixture 或者用于整个类的 fixture。之后,TestNG 为一个测试集合(定义在 TestNG 配置文件中并由 test 元素指定)定义了一个 fixture,为一组 测试(定义在 TestNG 的 Test 注释中)定义了一个 fixture。

测试细节

        创建一个 DbUnit fixture 并在测试级别上运行,这意味着运行任何测试之前,测试类的集合将共享相同的逻辑,为数据库正确地播种。在本文的示例中,在运行每个逻辑测试集合前,我希望数据库具有一组干净的数据。使用 DbUnit 的 CLEAN_INSERT 命令确保在先前运行的测试中创建的行被删除掉 —— 因此,我可以重新运行测试,该测试可以不断创建数据并且不用考虑数据库约束。

        此外,我希望 fixture 能够依赖参数化数据,这使我在运行某个测试之前,能够灵活地切换种子文件,甚至是特定数据库的位置。将 TestNG 与参数相关联起来再简单不过了:我所需做的仅仅是使用 Parameters 注释装饰 fixtrue,声明方法签名中相应的参数,并提供 TestNG 配置文件中的值。

        清单 8 定义了一个简单的 DbUnit fixture,它使用所需的种子文件播种数据库。请注意:该 fixture 被定义为包含五个 参数。(这可能非常多,但是在 fixture 中包含参数不是很好吗?)



 


鲜花

握手

雷人

路过

鸡蛋

扫一扫关注最新动态

毒镜头:老镜头、摄影器材资料库、老镜头样片、摄影
爱评测 aipingce.com  
返回顶部