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

时间:2022-10-18 15:19:44

在编写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文件, 并在文件中输入配置内容:

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="suite1">
<test name="test1">
<classes>
<class name="com.ui.day4.CalcTest" />
<class name="com.testng.demo_1" />
</classes>
</test>
</suite>

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

执行结果查看方式:

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

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

2、 testNG的Results可以查看

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

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

emailable-report.html报告单如下所示:
UI自动化测试(六)TestNG操作详解
index.html报告单如下所示:
UI自动化测试(六)TestNG操作详解

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文件定义的参数传递到测试程序或者测试类中来使用

 public class yihuqingjiu_test_demo {

         @Test
public void testCase1() {
System.out.println("in test case 1");
}
@Test
public void testCase2() {
System.out.println("in test case 2");
}
@BeforeMethod
public void beforeMethod() {
System.out.println("in beforeMethod");
}
@AfterMethod
public void afterMethod() {
System.out.println("in afterMethod");
}
@BeforeClass
public void beforeClass() {
System.out.println("in beforeClass");
}
@AfterClass
public void afterClass() {
System.out.println("in afterClass");
}
@BeforeTest
public void beforeTest() {
System.out.println("in beforeTest");
}
@AfterTest
public void afterTest() {
System.out.println("in afterTest");
}
@BeforeSuite
public void beforeSuite() {
System.out.println("in beforeSuite");
}
@AfterSuite
public void afterSuite() {
System.out.println("in afterSuite");
} }

运行结果:

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文件:

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1">
  <test name="exampletest1">
    <classes>
      <class name="com.ui.day1.test1" />
7     </classes>
  </test>
  <test name="exampletest2">
    <class name="com.ui.day2.test2">
      <methods>
        <include name="test01"></include>
      </methods>
    </class>
  </test>
</suite>

TestNG忽略测试

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

代码实现:

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

TestNG分组测试

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

 package com.ui.day4;

 import org.testng.Assert;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test; public class yihuqingjiu_test_group {
ca a;
@BeforeSuite(groups = {"冒烟","回归"})
public void reday() {
a = new ca();
}
@Test(groups = "冒烟")
public void add() {
Assert.assertEquals(a.add(5, 6), 11);
}
@Test(groups = "冒烟")
public void min() {
Assert.assertEquals(a.minus(6, 5), 1);
}
@Test(groups = "冒烟")
public void cheng() {
Assert.assertEquals(a.cheng(6, 5), 30);
}
@Test(groups = "回归")
public void cheng1() {
Assert.assertEquals(a.cheng(6, 5), 30);
}
@Test(groups = "回归")
public void chu() {
Assert.assertEquals(a.chu(5, 5), 1);
}
}

testng.xml文件配置如下:

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1" verbose="3">
<test name="test_one">
<groups>
<run>
<include name="回归" />
</run>
</groups>
<classes>
<class name="com.ui.day4.test_group"></class>
</classes>
</test>
</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属性去设 置,如下代码实现:

 public class yihuqingjiu_demo {
@Test(priority=2)
public void print3(){
  System.out.println("壶");
}
@Test(priority=0)
public void print1(){
System.out.println("温");
}
@Test(priority=1)
public void print2(){
System.out.println("一");
}
@Test(priority=4)
public void print5(){
System.out.println("酒");
}
@Test(priority=3)
public void print4(){
System.out.println("清");
}
}

执行顺序为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两种方式的比较

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

 public class NewTest {
WebDriver driver; @BeforeSuite
public void reday(){
driver=new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);
} @Test(priority=0)
public void index() throws Exception{
driver.get("http://127.0.0.1/iwebshop/");
String title=driver.getTitle();
//断言
//括号中前者是实际结果,后者是预期结果
Assert.assertEquals(title,"iWebShop开源电子商务平台");
Thread.sleep(2000);
} @Test(priority=1)
public void login() throws Exception{
driver.findElement(By.cssSelector("p.loginfo a")).click();
Thread.sleep(2000);
} @DataProvider(name="test")
public static Object[][] obj(){
return new Object[][]{{"username","654321"},{"username","123456"},{"username","654321"}};
}
@Test(dataProvider="test",priority=2)
public void userpassword(String a,String b) throws Exception {
driver.findElement(By.className("gray")).sendKeys(a);
Thread.sleep(1000);
driver.findElement(By.cssSelector("input[name='password']")).sendKeys(b);
Thread.sleep(1000);
System.out.println(a+":"+b);
driver.findElement(By.className("submit_login")).click();
Thread.sleep(2000); }

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