简介
TestNG是一个受JUnit和NUnit启发的测试框架 ,有完善的用例管理模块,配合Maven能够很方便管理依赖第三方插件。使用TestNG可以做功能、接口、单元、集成的自动化测试。
1. 注解
2. 参数化测试
3. 支持依赖测试方法
4. 支持组概念
5. 支持多线程测试
6. 灵活的配置
对比Junit
-
比Junit涵盖功能更全面
-
Junit更适合隔离性比较强的单元测试
-
TestNG更适合复杂的集成测试
使用步骤
-
编写测试的业务逻辑并在代码中插入TestNG annotation
-
将测试信息添加到testng.xml文件或build.xml中
-
运行TestNG
使用
依赖
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
</dependency>
</dependencies>
注解
@Test
@Test
public void test01(){
System.out.println("测试用例01");
}
运行结果:
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
测试用例01
===============================================
Default Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================
@BeforeMethod和@AfterMethod
每一个方法执行前执行BeforeMethod,每一个方法执行后执行AfterMethod
@AfterMethod
public void afterMethod(){
System.out.println("AfterMethod");
}
@BeforeMethod
public void beforeMethod(){
System.out.println("BeforeMethod");
}
@Test
public void test01(){
System.out.println("测试用例01");
}
@Test
public void test02(){
System.out.println("测试用例02");
}
运行结果:
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
BeforeMethod
测试用例01
AfterMethod
BeforeMethod
测试用例02
AfterMethod
===============================================
Default Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================
@BeforeClass和@AfterClass
测试类运行前执行BeforeClass,测试类运行后执行AfterClass
@BeforeMethod,@AfterMethod,@BeforeClass,@BeforeClass运行顺序如下
@AfterMethod
public void afterMethod(){
System.out.println("AfterMethod");
}
@BeforeMethod
public void beforeMethod(){
System.out.println("BeforeMethod");
}
@BeforeClass
public void beforeClass(){
System.out.println("BeforeClass");
}
@AfterClass
public void afterClass(){
System.out.println("AfterClass");
}
@Test
public void test01(){
System.out.println("测试用例01");
}
@Test
public void test02(){
System.out.println("测试用例02");
}
运行结果
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
BeforeClass
BeforeMethod
测试用例01
AfterMethod
BeforeMethod
测试用例02
AfterMethod
AfterClass
===============================================
Default Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================
@BeforeSuite和@AfterSuite
Suite可以包含多个类,在多个类运行之前执行BeforeSuite,多个类运行之后执行AfterSuite
套件测试
xml命名不限
package cn.fjx;
import org.testng.annotations.Test;
public class LoginTest {
@Test
public void login(){
System.out.println("登陆成功");
}
}
package cn.fjx;
import org.testng.annotations.Test;
public class SendMessageTest {
@Test
public void sendMessage(){
System.out.println("发送消息");
}
}
package cn.fjx;
import org.testng.annotations.*;
public class DemoTest {
@AfterMethod
public void afterMethod(){
System.out.println("AfterMethod");
}
@BeforeMethod
public void beforeMethod(){
System.out.println("BeforeMethod");
}
@BeforeClass
public void beforeClass(){
System.out.println("BeforeClass");
}
@AfterClass
public void afterClass(){
System.out.println("AfterClass");
}
@BeforeSuite
public void beforeSuit(){
System.out.println("BeforeSuite套件");
}
@AfterSuite
public void afterSuite(){
System.out.println("AfterSuite套件");
}
@Test
public void test01(){
System.out.println("测试用例01");
}
@Test
public void test02(){
System.out.println("测试用例02");
}
}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="test">
<test name="login">
<classes>
<class name="cn.fjx.DemoTest"></class>
<class name="cn.fjx.LoginTest"></class>
</classes>
</test>
<test name="sendMessage">
<classes>
<class name="cn.fjx.DemoTest"></class>
<class name="cn.fjx.SendMessageTest"></class>
</classes>
</test>
</suite>
运行testng.xml可以得到结果
[TestNG] Running:
D:\xh-code\TestDemo\src\main\resources\testng.xml
BeforeSuite套件
BeforeClass
BeforeMethod
测试用例01
AfterMethod
BeforeMethod
测试用例02
AfterMethod
AfterClass
登陆成功
BeforeClass
BeforeMethod
测试用例01
AfterMethod
BeforeMethod
测试用例02
AfterMethod
AfterClass
发送消息
AfterSuite套件
===============================================
test
Total tests run: 6, Failures: 0, Skips: 0
===============================================
忽略测试
忽略测试是指本次测试执行中不想要执行的测试方法
@Test(enabled = false)
@Test(enabled = false)
public void test01(){
System.out.println("测试用例01");
}
执行结果:
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
BeforeSuite套件
AfterSuite套件
===============================================
Default Suite
Total tests run: 0, Failures: 0, Skips: 0
===============================================
忽略测试时,Suite也会执行
@BeforeGroups和@AfterGroups
方法分组测试
BeforeGroups会在该组测试方法执行之前执行,AfterGroups会在该组测试方法执行之后执行
@BeforeGroups("apple")
public void appleBefore(){
System.out.println("appleBefore");
}
@AfterGroups("apple")
public void appleAfter(){
System.out.println("appleAfter");
}
@Test(groups = "apple")
public void apple1(){
System.out.println("apple1");
}
@Test(groups = "apple")
public void apple2(){
System.out.println("apple2");
}
@Test(groups = "pear1")
public void pear1(){
System.out.println("pear1");
}
@Test(groups = "pear2")
public void pear2(){
System.out.println("pear2");
}
运行结果:
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
appleBefore
apple1
apple2
appleAfter
pear1
pear2
===============================================
Default Suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================
类分组测试
可以选择组或者排除组进行测试,一组可以包含多个类
xml命名不限
package cn.fjx.group;
import org.testng.annotations.Test;
@Test(groups = "apple")
public class GroupOnClass01 {
public void apple01(){
System.out.println("apple01");
}
public void apple02(){
System.out.println("apple02");
}
}
package cn.fjx.group;
import org.testng.annotations.Test;
@Test(groups = "apple")
public class GroupOnClass02 {
public void apple01(){
System.out.println("apple01");
}
public void apple02(){
System.out.println("apple02");
}
}
package cn.fjx.group;
import org.testng.annotations.Test;
@Test(groups = "pear")
public class GroupOnClass03 {
public void pear01(){
System.out.println("pear01");
}
public void pear02(){
System.out.println("pear02");
}
}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="test">
<test name="runApple">
<groups>
<run>
<include name="apple"/>
</run>
</groups>
<classes>
<class name="cn.fjx.group.GroupOnClass01"></class>
<class name="cn.fjx.group.GroupOnClass02"></class>
<class name="cn.fjx.group.GroupOnClass03"></class>
</classes>
</test>
</suite>
运行结果:
[TestNG] Running:
D:\xh-code\TestDemo\src\main\resources\GroupsOnClass.xml
apple01
apple02
apple01
apple02
===============================================
test
Total tests run: 4, Failures: 0, Skips: 0
===============================================
异常测试
必须在方法中抛出异常,否则会报错
@Test(expectedExceptions = RuntimeException.class)
public void exception01(){
System.out.println("运行时异常01");
}
@Test(expectedExceptions = RuntimeException.class)
public void exception02(){
System.out.println("运行时异常02");
throw new RuntimeException();
}
运行结果
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
运行时异常01
org.testng.TestException:
Method ExceptionTest.exception01()[pri:0, instance:cn.fjx.exception.ExceptionTest@768debd] should have thrown an exception of type class java.lang.RuntimeException ...
运行时异常02
===============================================
Default Suite
Total tests run: 2, Failures: 1, Skips: 0
===============================================
依赖测试
某个方法执行时,必须先执行另外多个方法,这时可以使用dependsOnMethods
@Test
public void test01(){
System.out.println("test01");
}
@Test(dependsOnMethods = "test01")
public void test02(){
System.out.println("test02");
}
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
test01
test02
===============================================
Default Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================
当第一个方法出现异常时,第二个方法不会执行
@Test
public void test01(){
System.out.println("test01");
throw new RuntimeException();
}
@Test(dependsOnMethods = "test01")
public void test02(){
System.out.println("test02");
}
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
test01
java.lang.RuntimeException...
Test ignored.
===============================================
Default Suite
Total tests run: 2, Failures: 1, Skips: 1
===============================================
参数化测试
TestNG允许在TestMethod以及@Before/After类注解、@Factory类注解的方法中传入参数。 参数传递的方式有两种,一种是借助xml文件配置,另一种是以编码的方式传递参数。
- xml方式传递参数
xml命名不限
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="test">
<test name="param">
<classes>
<class name="cn.fjx.parameter.ParameterTest"/>
<parameter name="name" value="fjx"/>
<parameter name="age" value="20"/>
</classes>
</test>
</suite>
package cn.fjx.parameter;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParameterTest {
@Test
@Parameters({"name","age"})
public void test01(String name, Integer age){
System.out.println("name:"+name +" age:"+ age);
}
}
运行结果
[TestNG] Running:
D:\xh-code\TestDemo\src\main\resources\parameters.xml
name:fjx age:20
===============================================
test
Total tests run: 1, Failures: 0, Skips: 0
===============================================
- 编码的方式传递参数
为测试用例提供参数,有多少组参数就会执行多少次用例,因此它是一个让测试类实例的某个方法执行多次,但每次执行都使用同一个实例。
@Test(dataProvider = "data")
public void test02(String name, Integer age){
System.out.println("name:"+name +" age:"+ age);
}
@DataProvider(name = "data")
public Object[][] testData(){
return new Object[][]{
{"fjx01",123},
{"fjx02",456},
{"fjx03",789}
};
}
运行结果:运行test02会循环得到testData中的数据
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
name:fjx01 age:123
name:fjx02 age:456
name:fjx03 age:789
===============================================
Default Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
- @Factory
创建一个测试类的多个实例,每个实例中的所有测试用例都会被执行,因此它是一个测试类被执行多次,每次执行采用的是不同实例。
package cn.fjx.factory;
import org.testng.annotations.Factory;
public class SimpleTestFactory {
@Factory
public Object[] factoryMethod(){
return new Object[] { new SimpleTest(0), new SimpleTest(10)};
}
}
package cn.fjx.factory;
import org.testng.annotations.Test;
public class SimpleTest {
private int para;
public SimpleTest(int para) {
this.para = para;
}
@Test
public void testMethodOne(){
int value = para + 1;
System.out.println("Test method one output: " + value);
}
@Test
public void testMethodTwo(){
int value = para + 2;
System.out.println("Test method two output: " + value);
}
}
执行SimpleTestFactory得到运行结果:
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
Test method one output: 11
Test method one output: 1
Test method two output: 12
Test method two output: 2
===============================================
Default Suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================
超时测试
@Test(timeOut = 1000)
public void test01() throws InterruptedException {
Thread.sleep(2000);
}
运行结果:
[TestNG] Running:
C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml
org.testng.internal.thread.ThreadTimeoutException: Method cn.fjx.timeout.TimeOutTest.test01() didn't finish within the time-out 1000...
===============================================
Default Suite
Total tests run: 1, Failures: 1, Skips: 0
===============================================
testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<!--
suite有以下属性:
name:suite名称,测试报告中展现
verbose: 在控制台中如何输出,该设置不影响测试报告,可以设置0-10,越大输出越详细
allow-return-values:如果设置为false,被@Test注解且有return的方法被忽略执行
annotations:如果为"javadoc", 则使用javadoc注解,否则使用jdk注解
configfailurepolicy:字典:continue,skip,如果@Before*方法失败,TestNG是否应该继续执行套件中的其余测试,默认为skip
data-provider-thread-count:并发执行data-provider的线程数,默认大小为10
group-by-instances:默认情况下,依赖方法按类分组。例如,如果方法b()依赖于方法a(),并且您有几个包含这些方法的类实例(因为数据提供者的工厂),
那么调用顺序将为:signIn("us"),signIn("uk"),signOut("us"),signOut("uk")。group-by-instances设置为true的话,调用顺序将为:signIn("us"),signOut("us"),signIn("uk"),signOut("uk")
guice-stage:创建父注入器的stage
junit:是否以junit模式运行
object-factory:用于实现IObjectFactory的类,实例化测试对象
parallel:是否多线程并发运行测试,默认为false,字典:classes,methods,instances,tests,true,false
parent-module:用于创建所有guice注入器的父注入器的模块
preserve-order:默认情况下,TestNG将按照在XML文件配置的顺序运行测试。如果希望以不可预知的顺序运行文件中列出的类和方法,可将preserve-order属性设置为false
skipfailedinvocationcounts:是否跳过失败的调用
thread-count:使用并行模式,要使用的线程池的大小。
time-out:为具体执行单元设定一个超时时间,方法(parallel="methods")或测试(parallel="tests")
-->
<suite name="Suite" verbose="1">
<!--一个suite可以包含多个test,test有以下属性:
name:这个测试的名称(将出现在报告中)
annotations:同suite套件属性
allow-return-values:同suite套件属性
verbose:同suite套件属性
enabled:启用/禁用当前测试的标志。默认值:true
group-by-instances:同suite套件属性
junit:同suite套件属性
parallel:同suite套件属性
preserve-order:同suite套件属性
skipfailedinvocationcounts:同suite套件属性
thread-count:同suite套件属性
time-out:同suite套件属性
-->
<test name="test">
<!--指定执行包-->
<packages>
<!--包名称-->
<package name="com">
</package>
</packages>
</test>
<!--testng.xml中只能设置一个<suite>标签,可通过<suite-files >标签实现多个测试集设置。-->
<suite-files>
<suite-file path="testNG.xml"/>
<suite-file path="testNG.xml"/>
</suite-files>
<!--设置监听器-->
<listeners>
<listener class-name="TestNGHelloWorld1"/>
</listeners>
<!--方法拦截器-->
<method-selectors>
<method-selector>
<selector-class name="TestNGHelloWorld1"/>
</method-selector>
</method-selectors>
<!--方法拦截器-->
<method-selectors>
<method-selector>
<script language="java"/>
</method-selector>
</method-selectors>
<test name="TestNG1">
<groups>
<!--组中组,即test4包含了test1和test3两个组-->
<define name="test4">
<include name="test1"/>
<include name="test3"/>
</define>
<!--运行test4组,不运行test2组-->
<run>
<include name="test4"/>
<exclude name="test2"/>
</run>
<!--test3组依赖于test1,test2组,多个依赖用空格隔开-->
<dependencies>
<group name="test3" depends-on="test1 test2"/>
</dependencies>
</groups>
<!--类-->
<classes>
<class name="TestNGHelloWorld1"/>
</classes>
</test> <!-- TestNG -->
<test name="TestNG2">
<!--入参,分别为参数名和参数值-->
<parameter name="str" value="Test1"/>
<classes>
<class name="TestNGHelloWorld1">
<!--类中的方法-->
<methods>
<!--执行该方法-->
<include name="helloWorldTest1"/>
<!--不执行该方法-->
<exclude name="helloWorldTest2"/>
</methods>
</class>
</classes>
</test>
</suite>
网友评论