一、简介(单元测试框架,通过注解、分组、序列和参数化等多种方式组织和执行自动化测试脚本)
1、优点:
1)漂亮的html格式测试报告
2)支持并发测试
3)参数化测试更简单
4)支持更多功能的注解
二、安装testng
1、启动 Eclipse,点击“Help”菜单,点击“Install New Software”菜单项。
2、点击“Add”按钮
3、在 “Add Repository”界面的Name 输入框中输入“TestNG”,在Location 输入框中输入http://beust.com/eclipse 点击“OK”按钮
4、在“Install”界面中,勾选TestNG选项,点击“Next”按钮
5、开始TestNG 插件安装前的准备工作
6、在协议内容窗口中,点击选择“I accept the terms of the license agreement”,点击“Finish”按钮
7、开始安装TestNG插件
8、安装过程中,弹出警告框,点击“OK”按钮继续安装
9、安装完毕后,系统提示重启Eclipse,点击“Yes”按钮
10、Eclipse 重启后,在工程名称上方点击鼠标右键,在菜单中显示TestNG菜单项表示安装成功
三、导入TestNg
项目邮件——>Build Path——>Configure Buid Path——>add Libraty——>选择TestNg即可(若没有需要安装插件)
导入后就可看到
或者直接点项目邮件——》build path——》add library添加也可
四、TestNG 的常用注解
TestNG的常见测试用例组织结构:
* Test Suite 由一个或者多个 Test 组成
* Test 由一个或者多个测试 Class 组成
* 一个测试 Class 由一个或者多个测试方法组成
<!--在testing.xml的配置层级结构如下:-->
<suit>
<test>
<classes>
<method>
<method/>
<classes/>
<test/>
<suit/>
运行不同层级测试用例时,可通过不同注解实现测试前的初始化工作、测试用例执行工作和测试后的清理工作。
常用注解如下:
@BeforeSuite: 标示此注解的方法会在当前测试集合(suite)中的任一测试用例开始运行之前执行。
@AfterSuite: 标示此注解的方法会在当前测试集合(suite)中的所有测试程序运行结束之后执行。
@BeforeTest:标示此注解的方法会在Test 中任一测试用例开始运行前执行。
@AfterTest:标示此注解的方法会在Test 中所有测试用例运行结束后执行。
@BeforeGroups: 标示此注解的方法会在分组测试用例的任一测试用例开始运行前执行。
@AfterGroups: 标示此注解的方法会在分组测试用例的所有测试用例运行结束后执行。
@BeforeClass: 标示此注解的方法会在当前测试类的任一测试用例开始运行前执行。
@AfterClass: 标示此注解的方法会在当前测试类的所有测试用例运行结束后执行。
@BeforeMethod: 标示此注解的方法会在每个测试方法开始运行前执行。
@AfterMethod:: 标示此注解的方法会在每个测试方法运行结束后执行。
@Test: 标示此注解的方法会被认为是一个测试方法,即一个测试用例。
五、创建测试类
1、简单测试类(选择当前工程,右键new——》other——》Testng class)
package com.appium.testng;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.AfterSuite;
/**
* 1.@BeforeMethod和@AfterMethod会根据每次Test注解的出现而执行一遍(有几个test执行几次)
*/
public class Study1 {
@BeforeSuite
public void beforeSuite(){
System.out.println("beforeSuite——》在当前测试suite之前运行");
}
@AfterSuite
public void afterSuite(){
System.out.println("afterSuite——》在当前测试suite所有执行完成后执行");
}
@BeforeTest
public void beforeTest(){
System.out.println("beforeTest——》在test执行前执行");
}
@AfterTest
public void afterTest(){
System.out.println("afterTest——》在所有Test执行之后执行");
}
@BeforeClass
public void beforeClass(){
System.out.println("beforeClass——》在class执行前执行");
}
@AfterClass
public void afterClass(){
System.out.println("afterClass——》在class之后执行");
}
@BeforeMethod
public void beforeMethod(){
System.out.println("beforeMethod——》在每一个测试用例执行前执行");
}
@AfterMethod
public void afterMethod(){
System.out.println("afterMethod——》在每一个测试用例之后执行");
}
@Test
public void test1(){
System.out.println("test1——》执行测试test1");
}
@Test
public void test2(){
System.out.println("test2——》执行测试test2");
}
}
2、断言
TestNG 允许在测试执行过程中,对测试程序变量的中间状态进行断言(assert)判断,从而辅助判断测试用例的执行是成功还是失败。
TestNG中常用的断言方法如下:
assertTrue 判断是否为true
assertFalse 判断是否为false
assertSame 判断引用地址是否相同
assertNotSame 判断引用地址是否不相。
assertNull 判断是否为null
assertNotNull 判断是否不为null
assertEquals 判断是否相等,Object类型的对象需要实现hashCode及equals方法
assertNotEquals 判断是否不相等
assertEqualsNoOrder 判断忽略顺序是否相等
package com.appium.testng;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class Study2 {
@Test(groups="add")
public void add1(){
System.out.println("test add1");
int a=7,b=8;
int sum=a+b;
Assert.assertEquals(sum, 15,"add error");
}
@Test(groups="add")
public void add2(){
System.out.println("test add2");
int a=7,b=8;
int sum=a+b;
Assert.assertEquals(sum, 15,"add error");
}
@Test(groups="sub")
public void sub1(){
System.out.println("test sub1");
int a=7,b=8;
int sum=a-b;
Assert.assertEquals(sum, 14,"sub error");
}
@BeforeClass
public void before(){
System.out.println("before222");
}
}
通过TestNG.xml 的配置,可实现运行多个测试用例的不同组合。
创建testng.xml文件,右键选择项目new——>File——>写入文件名testng.xml
执行xml文件,在testng.xml文件上右键->run as->Testng Suite,可执行class标签里写的测试类,这里也可以写多个class标签
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<test verbose="2" name="Default test">
<classes>
<class name="com.appium.testng.Study1"></class>
<class name="com.appium.testng.Study2"></class>
</classes>
</test>
</suite>
执行结果
3、测试集合:添加group
在自动化测试的执行过程中,通常会产生批量运行多个测试用例的需求,此需求称之为运行测试集合(Test Suite)。TestNG 的测试用例可以是相互独立的,也可以按照特定的顺序来执行。
stNG 使用“group”关键字进行分组,用来执行多个Test的测试用例。
package com.appium.testng;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class Study2 {
@Test(groups="add1")
public void add1(){
System.out.println("test add1");
int a=7,b=8;
int sum=a+b;
Assert.assertEquals(sum, 14,"add error");
}
@Test(groups="add2")
public void add2(){
System.out.println("test add2");
int a=7,b=8;
int sum=a+b;
Assert.assertEquals(sum, 14,"add error");
}
@Test(groups="sub")
public void sub1(){
System.out.println("test sub1");
int a=7,b=8;
int sum=a-b;
Assert.assertEquals(sum, 14,"sub error");
}
@BeforeClass
public void before(){
System.out.println("before222");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<test verbose="2" name="Default test">
<groups>
<run>
<include name="add1"></include><!--执行分组-->
<include name="add2"></include><!--执行分组-->
<exclude name="sub"></exclude><!--不执行这个分组-->
</run>
</groups>
<classes>
<class name="com.appium.testng.Study1"></class>
<class name="com.appium.testng.Study2"></class>
</classes>
</test>
</suite>
执行全部分组的配置文件
执行全部分组的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite">
<test name="Test1">
<groups>
<define name="All">
<include name="add1"/>
<include name="add2"/>
<include name="sub"/>
</define>
<run>
<include name="All"/>
</run>
</groups>
<classes>
<class name="com.appium.com.Study3"/>
</classes>
</test>
</suite>
4、依赖测试:如先登录后进行业务操作
某些复杂的测试场景需要按照某个特定顺序执行测试用例,以此保证某个测试用例被执行之后才执行其它测试用例,此测试场景运行需求称之为依赖测试。通过依赖测试,可在不同测试方法间共享数据和程序状态。TestNG支持依赖测试,使用dependsOnMethods及dependsOnGroups参数来实现。
package com.appium.testng;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class Study3 {
@Test(groups="init")
public void startApp(){
System.out.println("start app");
}
@Test(dependsOnMethods={"startApp"},groups="init")
public void login(){
System.out.println("login app");
}
@Test(dependsOnMethods={"login"},groups="testcase")
public void search(){
System.out.println("search file");
}
@Test(dependsOnMethods={"login","search"},groups="testcase")
public void settings(){
System.out.println("Personal settings");
}
@Test(dependsOnGroups={"testcase"},groups="end")
public void logout(){
System.out.println("logout app");
}
}
配置文件如下
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite">
<test name="Test1">
<groups>
<define name="All">
<include name="sub"/>
<include name="add"/>
<include name="init"/>
<include name="testcase"/>
<include name="end"/>
</define>
<run>
<include name="init"/>
<include name="testcase"/>
<include name="end"/>
</run>
</groups>
<classes>
<class name="com.appium.testng.Study3"/>
</classes>
</test>
</suite>
5、用例顺序
1、使用参数Priority可实现按照特定顺序执行测试用例,此方法对配置文件中的所有class起作用
package com.appium.testng;
import org.testng.annotations.Test;
public class PriorityStudy {
@Test(groups="priorityTest",priority=1)
public void priorityOne(){
System.out.println("顺序一");
}
@Test(groups="priorityTest",priority=3)
public void priorityThree(){
System.out.println("顺序三");
}
@Test(groups="priorityTest",priority=2)
public void priorityTwo(){
System.out.println("顺序二");
}
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="Suite">
<test name="Test1">
<groups>
<define name="All">
<include name="sub"/>
<include name="add1"/>
<include name="init"/>
<include name="testcase"/>
<include name="end"/>
<include name="ordertest"/>
</define>
<run>
<include name="priorityTest"/>
</run>
</groups>
<classes>
<class name="com.mytesting.fourday.PriorityStudy"/>
</classes>
</test>
</suite>
执行结果如下:
2、按照类中的方法的首写字母拍列顺序
3、根据依赖关系
4、忽略测试
使用参数 enabled=false 来忽略某测试方法,在执行时将不会执行此属性的测试方法
package com.appium.testng;
import org.testng.annotations.Test;
public class PriorityStudy {
@Test(groups="priorityTest",priority=1)
public void priorityOne(){
System.out.println("顺序一");
}
@Test(groups="priorityTest",priority=3,enabled=false)
public void priorityThree(){
System.out.println("顺序三");
}
@Test(groups="priorityTest",priority=2)
public void priorityTwo(){
System.out.println("顺序二");
}
}
六、数据驱动
Testng提供了数据驱动模式,以DataProvider注解完成,一般做参数化,返回一个二维数组,使用这个注解不用指定循环次数,他会根据驱动数据值自动执行所有的数据
@DataProvider
public Object[][] logigDate(){
//有3组数据,登录用例会执行3次
Object[][] obj={{"name1","pwd1","assert1"},
{"name2","pwd2","assert2"},
{"name3","pwd3","assert3"}};
return obj;
}
@Test(groups="init")
public void startApp(){
System.out.println("start app");
}
@Test(dependsOnMethods={"startApp"},groups="init",dataProvider="logigDate")
public void login(String name,String pwd,String assertValue){
System.out.println("login app");
System.out.println("name:"+name+" "+"pwd:"+pwd+" "+"assertValue:"+assertValue);
}
testng.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<!-- parallel从哪个层级开始并发,此处是test表示test标签,thread-count线程数为几个就需要设置几个test标签 -->
<suite name="Default suite" parallel="tests" thread-count="2">
<test name="Test1">
<!-- <parameter name="name" value="jff"/>
<parameter name="age" value="18"/> -->
<classes>
<class name="com.appium.testng.Study3"/>
</classes>
</test>
</suite>
执行结果
七、并发执行测试(从配置文件中向脚本中传参,这个需要在脚本中接受传来的参数)
//@Parameters注释表示从配置文件中的变量名称取值
@Parameters({"name","age"})
@Test(groups="testcase")
public void nameAndAge(String name ,String age){
System.out.println("name:"+name+" "+"age:"+age);
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<!-- parallel从哪个层级开始并发,此处是test表示test标签,thread-count线程数为几个就需要设置几个test标签 -->
<suite name="Default suite" parallel="tests" thread-count="2">
<test name="Test1">
<parameter name="name" value="jff"/>
<parameter name="age" value="18"/>
<groups>
<run>
<include name="bingfa"></include>
</run>
</groups>
<classes>
<class name="com.appium.testng.Study3"/>
</classes>
</test>
<test name="Test2">
<parameter name="name" value="xuancheng"/>
<parameter name="age" value="1"/>
<classes>
<!-- 执行顺序是配置的顺序,但如果类中有beforeclass则从beforeclass则先执行 -->
<class name="com.appium.testng.Study3"/>
</classes>
</test>
</suite>
执行结果: