UI自动化测试(六)TestNG操作详解

在编写TestNG代码的时候,若没有下载TestNG的jar包的话,代码会出错,下载jar包方法见该链接中java+selenium环境搭建的第二步即可:http://www.cnblogs.com/hong-fithing/p/7622215.html

运行测试步骤方法有如下两种:

1、 直接在Eclipse运行testNG的测试用例, 在代码编辑区域鼠标右键, 选择Run as ->testNG Test
2、 在工程的根目录下, 建立testng.xml文件, 并在文件中输入配置内容:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
 3 <suite name="suite1">
 4     <test name="test1">
 5         <classes>
 6             <class name="com.ui.day4.CalcTest" />
 7             <class name="com.testng.demo_1" />
 8         </classes>
 9     </test>
10 </suite>

然后在工程中的testNG.xml上方鼠标右键单击, 在弹出的菜单中选择Run as ->Test Suite即可运行测试用例,suite代表一个XML文件。 它可以包含一个或多个测试, 并被定义由<suite>标记标签<test>代表一个测试, 并可以包含一个或多个TestNG的类<class>的标签代表一个TestNG的类是一个Java类,它包含至少一个TestNG的注解。它可以包含一个或多个测试方法。

执行结果查看方式:

1、 在Console可以查看测试结果

2、 testNG的Results可以查看

3、 testNG的Html格式测试报告, 该测试报告存在与工程目录下的“test-output”目录下,emailable-report.html和index.html。

emailable-report.html报告单如下所示:
index.html报告单如下所示:

TestNG常用注解annotation

注解 描述
@BeforeSuite 被注释的方法将在所有测试运行前运行(相当于前置条件)
@AfterSuite

被注释的方法将在所有测试运行后运行比如关闭浏览器(使执行其他用例时处于初始状态)

@BeforeTest 被注释的方法将在测试运行前运行
@AfterTest 被注释的方法将在测试运行后运行
@BeforeGroups

被配置的方法将在列表中的gourp前运行。这个方法保证在第一个属于这些组的测试方法调用

立即执行

@AfterGroups

被配置的方法将在列表中的gourp后运行。这个方法保证在最后一个属于这些组的测试方法调

后立即执行

@BeforeClass 被注释的方法将在当前类的第一个测试方法调用前运行
@AfterClass 被注释的方法将在当前类的所有测试方法调用后运行
@BeforeMethod 被注释的方法将在每一个测试方法调用前运行
@AfterMethod 被注释的方法将在每一个测试方法调用后运行
@DataProvider 

标记一个方法用于为测试方法提供数据。 被注释的方法必须返回Object[][],其中每Object[]

可以指派为这个测试方法的参数列表。从这个DataProvider接收数@Test要使用一个和

当前注释相同名称的dataProvider名称

@Factory

标记方法作为一个返回对象的工厂, 这些对象将被TestNG用于作为测试类。个方必须返回

Object[]

@Listeners 定义一个测试类的监听器
@Parameters 描述如何传递参数给@Test方法
@Test 标记一个类或方法作为测试的一部分

 

备注:

Before开头的注解一般用于初始化环境、 准备测试环境
after开头的注解一般用于执行测试的环境清理工作
DataProvider一般用作参数化用的, 属于数据驱动自动化(即不同的测试数据测试相同的测试逻辑)
Listeners 自定义日志或者监控一些testNG用例执行成功或者失败的时候做些特别的事情
Parameters可以把xml文件定义的参数传递到测试程序或者测试类中来使用

 1 public class yihuqingjiu_test_demo {
 2 
 3         @Test
 4         public void testCase1() {
 5         System.out.println("in test case 1");
 6         } 
 7         @Test
 8         public void testCase2() {
 9         System.out.println("in test case 2");
10         } 
11         @BeforeMethod
12         public void beforeMethod() {
13         System.out.println("in beforeMethod");
14         } 
15         @AfterMethod
16         public void afterMethod() {
17         System.out.println("in afterMethod");
18         }
19         @BeforeClass
20         public void beforeClass() {
21         System.out.println("in beforeClass");
22         } 
23         @AfterClass
24         public void afterClass() {
25         System.out.println("in afterClass");
26         } 
27         @BeforeTest
28         public void beforeTest() {
29         System.out.println("in beforeTest");
30         } 
31         @AfterTest
32         public void afterTest() {
33         System.out.println("in afterTest");
34         } 
35         @BeforeSuite
36         public void beforeSuite() {
37         System.out.println("in beforeSuite");
38         } 
39         @AfterSuite
40         public void afterSuite() {
41         System.out.println("in afterSuite");
42         } 
43 
44 }

 

运行结果:

in beforeSuite
in beforeTest
in beforeClass
in beforeMethod
in test case 1
in afterMethod
in beforeMethod
in test case 2
in afterMethod
in afterClass
in afterTest

TestNG的执行过程如下:
首先beforeSuite()方法执行一次。
最后afterSuite()方法执行一次。
其次方法 beforeTest(), beforeClass(), afterClass() afterTest() 方法各执行一次。
beforeMethod()方法在执行每个测试用例之前执行一次。
afterMethod()方法在执行每个测试用例之后执行一次。

TestNG测试套件

测试套件是为了测试软件程序的行为或一系列行为, 是一个集合。 在TestNG中, 不能在测试源代码中引入测试集合, 但可以用testng.xml文件来进行测试套件的配置。

Testng.xml文件节点属性

suite常用属性介绍
注解 描述
@name suite的名称, 必须参数
@verbose 命令行信息打印等级, 不会影响测试报告输出内容; 可选值(1|2|3|4|5)
@parallel

是否多线程并发运行测试; 可选值(false | methods | tests | classes |instances)默认 "false"

@thread-count 当为并发执行时的线程池数量, 默认为"5"
@annotations 获取注解的位置, 如果为"javadoc", 则使用javadoc注解, 否则使用jdk注解
junit 是否以Junit模式运行, 可选值(true | false), 默认"false"
@time-out 为具体执行单元设定一个超时时间, 具体参照parallel的执行单元设置; 单位为毫秒

 

test常用属性说明
注解 描述
@name test的名字, 必选参数; 测试报告中会有体现
@verbose 命令行信息打印等级, 不会影响测试报告输出内容; 可选值(1|2|3|4|5)
@parallel

是否多线程并发运行测试; 可选值(false | methods | tests | classes |instances)默认 "false"

@thread-count 当为并发执行时的线程池数量, 默认为"5"
@annotations 获取注解的位置, 如果为"javadoc", 则使用javadoc注解, 否则使用jdk5注解
@time-out 为具体执行单元设定一个超时时间, 具体参照parallel的执行单元设置; 单位为毫秒
@enabled 设置当前test是否生效, 可选值(true | false), 默认"true"

 

testng.xml中有<suite>根标签。 它描述了一个测试套件, <suite>由一个或多个<test>区段组成, 如下testng.xml文件: 

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
 3 <suite name="Suite1">
 4   <test name="exampletest1">
 5     <classes>
 6       <class name="com.ui.day1.test1" />
 7     </classes>
 8   </test>
 9   <test name="exampletest2">
10     <class name="com.ui.day2.test2">
11       <methods>
12         <include name="test01"></include>
13       </methods>
14     </class>
15   </test>
16 </suite>

TestNG忽略测试

当测试用例还没准备好,可以给测试用例加上@Test(enable =false),来禁用此测试用例。

代码实现:

@Test(enabled = false)
public void add(){
  Assert.assertEquals(a.add(5, 6), 11);
}

TestNG分组测试

顾名思义,是将不同的用例分组,然后再testng.xml文件中配置信息,而执行相应组的用例,代码实现如下,仅供参考:

 1 package com.ui.day4;
 2 
 3 import org.testng.Assert;
 4 import org.testng.annotations.BeforeSuite;
 5 import org.testng.annotations.Test;
 6 
 7 public class yihuqingjiu_test_group {
 8     ca a;
 9   @BeforeSuite(groups = {"冒烟","回归"})
10   public void reday() {
11       a = new ca();
12   }
13   @Test(groups = "冒烟")
14   public void add() {
15       Assert.assertEquals(a.add(5, 6), 11);
16   }
17   @Test(groups = "冒烟")
18   public void min() {
19       Assert.assertEquals(a.minus(6, 5), 1);
20   }
21   @Test(groups = "冒烟")
22   public void cheng() {
23       Assert.assertEquals(a.cheng(6, 5), 30);
24   }
25   @Test(groups = "回归")
26   public void cheng1() {
27       Assert.assertEquals(a.cheng(6, 5), 30);
28   }
29   @Test(groups = "回归")
30   public void chu() {
31       Assert.assertEquals(a.chu(5, 5), 1);
32   }
33 }

testng.xml文件配置如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
 3 <suite name="Suite1" verbose="3">
 4     <test name="test_one">
 5         <groups>
 6             <run>
 7                 <include name="回归" />
 8             </run>
 9         </groups>
10         <classes>
11             <class name="com.ui.day4.test_group"></class>
12         </classes>
13     </test>
14 </suite>

TestNG依赖测试

按顺序来调用测试用例,那么测试用例之间就存在依赖关系,TestNG支持测试用例之间的依赖。TestNG中通过dependsOnMethods属性来配置依赖方法。

实现如下:

@Test(dependsOnMethods = { "minus" })
  public void add() {
      Assert.assertEquals(a.add(5, 6), 11);
  }

备注: add测试用例执行的前提条件是必须minus测试方法执行,如果minus用例的属性设置为enabled = false,那么执行测试的时候就会报错,因为minus不执行。 注意:被依赖的测试用例必须执行成功才运行下一个测试用例,dependsOnGroups依赖于测试组

TestNG自定义执行顺序

按照一定的顺序去执行测试方法, 通过priority属性去设 置,如下代码实现:

 1 public class yihuqingjiu_demo {
 2      @Test(priority=2)
 3      public void print3(){
 4       System.out.println("壶");
 5      } 
 6      @Test(priority=0)
 7      public void print1(){
 8          System.out.println("温");
 9      } 
10      @Test(priority=1)
11      public void print2(){
12          System.out.println("一");
13      }
14      @Test(priority=4)
15      public void print5(){
16          System.out.println("酒");
17      }
18      @Test(priority=3)
19      public void print4(){
20          System.out.println("清");
21      }
22  }  

执行顺序为print1--->print2--->print3--->print4--->print5
属性值为0代表最高优先级

还可以在testng.xml文件中设置,设置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1">
  <test name="test" preserve-order="true">
    <classes>
      <class name="com.ui.day4.test_demo">
        <methods>
          <include name="print5" />
          <include name="print2" />
          <include name="print4" />
          <include name="print1" />
          <include name="print3" />         </methods>       </class>     </classes>   </test> </suite>

preserve-order属性设置为true
依据include配置的顺序执行测试方法

TestNG参数化测试

软件测试中, 经常需要测试大量的数据集。 测试代码的逻辑完全一样, 只是测试的参数不一样。 这样我们就需要一种 “传递测试参数的机制” 。 避免写重复的测试代码。

 

TestNG提供了2种传递参数的方式:

第一种: testng.xml 方式使代码和测试数据分离,方便维护;

第二种: @DataProvider能够提供比较复杂的参数。(也叫data-driven testing)

 

使用testng.xml设置参数:

1、 参数在xml文件中可以在suite级别定义, 也可以在test级别定义;

2、 TestNG会尝试先在包含当前类的test标签中寻找参数, 如果没找到则在上层的suite标签中查找。 即在test标签中相同的参数对当前类当前方法的优先级比较高。

3、 TestNG支持这种传参方式的类型如下:

String、 int/Integer、 boolean/Boolean、 byte/Byte、 char/Character、double/Double、 float/Float、 long/Long、 short/Short

 

使用@DataProvider方式传参数:

只提供了一个字符串属性:名称,供测试方法作为传递参数的annotation使用两种DataProvider,一种是返回一个二维数组对象; 另外一种DataProvider是返回一个Iterator

DataProvider可以向测试方法传递任意类型任意数目的参数利用DataProvider提供不同的参数集合对一个测试方法进行多次调用

 

@DataProvider和testNG.xml两种方式的比较

 1 public class NewTest {
 2     WebDriver driver;
 3     
 4     @BeforeSuite
 5     public void reday(){
 6     driver=new ChromeDriver();
 7     driver.manage().window().maximize();
 8     driver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);
 9     }
10     
11     @Test(priority=0)
12     public void index() throws Exception{
13         driver.get("http://127.0.0.1/iwebshop/");
14         String title=driver.getTitle();
15         //断言
16         //括号中前者是实际结果,后者是预期结果
17         Assert.assertEquals(title,"iWebShop开源电子商务平台");
18         Thread.sleep(2000);
19     }
20     
21     @Test(priority=1)
22     public void login() throws Exception{
23         driver.findElement(By.cssSelector("p.loginfo a")).click();
24         Thread.sleep(2000);
25     }
26   
27   @DataProvider(name="test")
28     public static Object[][] obj(){
29     return new Object[][]{{"username","654321"},{"username","123456"},{"username","654321"}};
30     }
31     @Test(dataProvider="test",priority=2)
32     public void userpassword(String a,String b) throws Exception {
33         driver.findElement(By.className("gray")).sendKeys(a);
34         Thread.sleep(1000);
35         driver.findElement(By.cssSelector("input[name='password']")).sendKeys(b);
36         Thread.sleep(1000);
37         System.out.println(a+":"+b);
38         driver.findElement(By.className("submit_login")).click();
39         Thread.sleep(2000);
40         
41     }

用户名和密码依次传递给变量a和b,重复登录操作

posted @ 2017-09-19 20:50  温一壶清酒  阅读(3071)  评论(0编辑  收藏  举报