TestNG
TestNG 介绍
TestNG 也是一套测试框架,表示下一代(next genaration),它的灵感来源于 Junit(.java 的单元测试框架)和 Nunit(.net 的单元测试框架),但是它又在此基础上引入了新的东西,使得它更加强大。
TestNG 是一个设计用来简化广泛的测试需求的测试框架,从单元测试(隔离测试一个类)到集成测试(测试由有多个类多个包甚至多个外部框架组成的整个系统,例如应用服务器)。
TestNG 的优点:
- 漂亮的 HTML 格式测试报告
- 支持并发测试
- 参数化测试更简单
- 支持输出日志
- 支持更多功能的注解
- 不仅支持单元测试,还支持集成测试
TestNG 使用步骤:
- 编写测试代码逻辑
- 插入 TestNG 注解标签
- 配置 Testng.xml 文件,设定测试类、测试方法、测试分组等执行信息
- 运行 TestNG 的测试程序(java 文件或 xml 配置文件均可右键运行)
Maven TestNG 依赖:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
<scope>test</scope>
</dependency>
TestNG 常用注解
TestNG 支持多种注解,可以进行各种组合,如下进行简单的说明:
注解 | 描述 |
---|---|
@BeforeSuite | 在该套件的所有测试都运行在注释的方法之前。仅运行一次 |
@AfterSuite | 在该套件的所有测试都运行在注释方法之后。仅运行一次 |
@BeforeClass | 在调用当前类的第一个测试方法之前运行。注释方法仅运行一次 |
@AfterClass | 在调用当前类的第一个测试方法之后运行。注释方法仅运行一次 |
@BeforeTest | 注释的方法将在属于 test 标签内的类的所有测试方法运行之前运行 |
@AfterTest | 注释的方法将在属于 test 标签内的类的所有测试方法运行之后运行 |
@BeforeGroups | 配置方法将在之前运行组列表。 此方法保证在调用属于这些组中的任何一个的第一个测试方法之前不久运行 |
@AfterGroups | 此配置方法将在之后运行组列表。 该方法保证在调用属于任何这些组的最后一个测试方法之后不久运行 |
@BeforeMethod | 注释方法将在每个测试方法之前运行 |
@AfterMethod | 注释方法将在每个测试方法之后运行 |
@DataProvider | 标记一种方法来提供测试方法的数据。 注释方法必须返回一个 Object[][],其中每个 Object[] 可以被分配给测试方法的参数列表; 要从该 DataProvider 接收数据的 @Test 方法需要使用与此注释名称相等的 dataProvider 名称 |
@Factory | 将一个方法标记为工厂,返回TestNG将被用作测试类的对象。 该方法必须返回 Object[] |
@Listeners | 定义测试类上的侦听器 |
@Parameters | 描述如何将参数传递给 @Test 方法 |
@Test | 将类或方法标记为测试的一部分。 若此标记若放在类上,则该类所有公共方法都将被作为测试方法 |
TestNG 的执行顺序如下:
@BeforeSuite > @BeforeTest > @BeforeMethod > @Test > @AfterMethod > @AfterTest > @AfterSuite
TestNG 常用断言
硬断言
在 TestNg 中,Assert 类为硬断言,里面有多个静态方法被称为硬断言。特点就是,如果脚本运行断言失败,马上停止运行,后面代码将不会被执行。
TestNG 中提供了多个形如 assert*() 的方法,主要是匹配不同的数据类型和集合类及其他对象操作。
方法名 | 说明 |
---|---|
assertEquals(actual, expected) | 查看两个对象是否相等。类似于字符串比较使用的 equals() 方法 |
assertNotEquals(actual, expected) | 查看两个对象是否不相等 |
assertNull(object) | 查看对象是否为空 |
assertNotNull(object) | 查看对象是否不为空 |
assertSame(actual, expected) | 查看两个对象的引用是否相等。类似于使用“=-”比较两个对象 |
assertNotSame(actual, expected) | 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象 |
assertTrue(condition) | 查看运行结果是否为 true |
assertFalse(condition) | 查看运行结果是否为 false |
assertArrayEquals(actual.expected) | 查看两个数组是否相等 |
fail() | 让测试失败 |
软断言
在 TestNg 中,SoftAssert 类为软断言。特点是如果运行断言失败,不会停止运行,会继续执行这个断言下的其他语句或者断言,不影响其他断言的运行。
使用说明:assertAll() 一定要放在该测试类的最后一个断言后面,软断言的类叫 SoftAssert.java,这个类是需要创建实例对象的,才能调用相关实例方法进行软断言。
示例:
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
public class TestSoftAssert {
@Test
public void testSoftAssert(){
System.out.println("脚本执行开始");
// 实例化 SoftAssert
SoftAssert assertion = new SoftAssert();
assertion.assertEquals(5, 6, "我俩不是一样大");
System.out.println("脚本执行结束");
System.out.println("我是观望,到这会不会执行的");
// 这个必须放到最后,没什么可说的
assertion.assertAll();
}
}
执行结果:
...
脚本执行开始
脚本执行结束
我是观望,到这会不会执行的
java.lang.AssertionError: The following asserts failed:
我俩不是一样大
Expected :6
Actual :5
...
通过执行结果发现,在断言 5 和 6 相等的这行代码后,还有其他的语句。如果这里采用的是硬断言,那么后面的"脚本执行结束"和"我是观望,到这会不会执行的"是不会输出的,这就是 SoftAssert 的特点。
group:分组
- 把在一个 Test 标签内的中所有类方法再进行分组。在运行时,一个组的方法会一起运行,然后再运行下一个组的方法;
- 分组的最小维度为方法,当把带分组的 @Test(groups="groupName") 注解对类使用时,这个测试类中的所有方法都属于这同一个组;
- 一个方法也可以同时属于多个组,如 @Test(groups={"groupName1", "groupName2"}),那么每组运行时这个方法都会被执行一次;
- 同一个组里的方法类,如果分别属于两个不同的测试用例(\Test 标签)内,那么它们其实可以算两个组,它们会在每个测试用例分别运行,而不会合在一起运行。
示例:
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
public class GroupTest {
@BeforeGroups(groups="server")
public void beforeGroupsOnServer() {
System.out.println("服务端组运行前执行的方法。。。");
}
@BeforeGroups(groups="client")
public void beforeGroupsOnClient() {
System.out.println("客户端组运行前执行的方法。。。");
}
@Test(groups="server")
public void test1() {
System.out.println("server test1 run ....");
}
@Test(groups="server")
public void test2() {
System.out.println("server test2 run ....");
}
@Test(groups="client")
public void test3() {
System.out.println("client test3 run ....");
}
@Test(groups="client")
public void test4() {
System.out.println("client test4 run ....");
}
@AfterGroups(groups="server")
public void afterGroupsOnServer() {
System.out.println("服务端组运行之后执行的方法。。。");
}
@AfterGroups(groups="client")
public void afterGroupsOnClient() {
System.out.println("客户端组运行之后执行的方法。。。");
}
}
执行结果:
服务端组运行前执行的方法。。。
server test1 run ....
server test2 run ....
服务端组运行之后执行的方法。。。
客户端组运行前执行的方法。。。
client test3 run ....
client test4 run ....
客户端组运行之后执行的方法。。。
enable:忽略执行
默认是 true , 如果设置为 false ,则表示在运行时不会执行这个测试方法。
示例:
import org.testng.annotations.Test;
public class EnableTest {
@Test
public void ignore1() {
System.out.println("ignore1 run ...");
}
@Test(enabled = false)
public void ignore2() {
System.out.println("ignore2 run ...");
}
@Test
public void ignore3() {
System.out.println("ignore3 run ...");
}
}
执行结果:
ignore1 run ...
ignore3 run ...
expectedExeption:预期异常
示例:@Test(expectedExceptions=ClassName.class) 表示若测试代码抛出了预期想要的异常类(ClassName),则测试通过,没有异常则算测试不通过。
expectedExceptions 的值也可以是一个数组,如:@Test(expectedExceptions={ClassName.class, ClassName2.class, ...})
示例:
import org.testng.annotations.Test;
public class ExpectedException {
/**
* 运行时异常,我们期望返回一个运行时异常,这条用例才是正确的。
*/
@Test(expectedExceptions = RuntimeException.class, enabled = false)
public void runTimeExceptionFailed() {
System.out.println("没有抛出异常,这条用例不通过!");
}
/**
* 结果抛出了一个运行时异常,和我们的期望一致,测试通过。
*/
@Test(expectedExceptions = RuntimeException.class)
public void runTimeExceptionSuccess() {
System.out.println("程序抛出了运行时异常,测试用例通过!");
throw new RuntimeException();
}
}
执行结果:
程序抛出了运行时异常,测试用例通过!
dependsOnMethods:依赖方法
在被依赖的方法运行完成之后运行当前方法,如果依赖方法测试不通过,那么当前方法也不会继续运行。
依赖的方法可以有多个,例:@Test(dependsOnMethods={"methodName1", "methodName2"})
示例:
import org.testng.annotations.Test;
/**
*
*/
public class DependTest {
@Test
public void test1() {
System.out.println("test1 run ...");
}
/**
* test2 运行时,需要依赖 test1 的运行
* 如果 test1 运行失败,会直接忽略 test2,test2 就不会执行了
*/
@Test(dependsOnMethods = {"test1"})
public void test2() {
System.out.println("test2 run ...");
}
}
执行结果:
test1 run ...
test2 run ...
属性总结
属性名 | 描述 |
---|---|
alwaysRun | 设置为 true 时,无论什么情况都会运行 |
dataProvider | 数据提供者的名称 |
dataProviderClass | 如果未指定,将在当前测试方法的类或其父类之一上查找数据提供者; 如果指定了此属性,则数据提供者方法在指定的类上必须是静态的 |
dependsOnGroups | 依赖的组列表 |
dependsOnMethods | 依赖的方法列表 |
description | 说明 |
enabled | 默认为true,设置为 false 时失效 |
expectedExceptions | 预期测试方法将引发的异常列表。 如果未引发任何异常或与该列表中的异常不同,则此测试将标记为失败 |
groups | 所属组 |
invocationCount | 调用次数 |
invocationTimeOut | 所有 invocationCount 的累积超时时间。 注意:如果未指定 nvocationCount,则将忽略此属性 |
priority | 此测试方法的优先级 |
successPercentage | 该方法预期成功的百分比 |
singleThreaded | 如果设置为 true,则即使当前正在使用 parallel ="methods" 运行测试,也保证该测试类上的所有方法都可以在同一线程中运行。 此属性只能在类级别使用,如果在方法级别使用,则将被忽略 |
timeOut | 超时时间。如果测试运行时间长于该定义时间,测试失败(单位为毫秒) |
threadPoolSize | 此方法的线程池的大小。 该方法将从 invocationCount 指定的多个线程中调用。 注意:如果未指定 invocationCount,则忽略此属性 |
TestNG 配置文件
使用示例
- 测试类:
import org.testng.annotations.AfterGroups;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class TestConfig {
@BeforeSuite
public void beforeSuite() {
System.out.println("测试套件(当前xml中<suite>标签)之前运行@BeforeSuite--------------------");
}
@AfterSuite
public void afterSuite() {
System.out.println("测试套件(当前xml中<suite>标签)之后运行@AfterSuite--------------------\n");
}
@BeforeTest
public void beforeTest() {
System.out.println("测试用例(当前xml中<test>标签)之前运行@BeforeTest----------");
}
@AfterTest
public void afterTest() {
System.out.println("测试用例(当前xml中<test>标签)之后运行@AfterTest----------\n");
}
@BeforeMethod
public void beforeMethod() {
System.out.println("当前类每个测试方法(@Test)之前运行@BeforeMethod");
}
@AfterMethod
public void AfterMethod(){
System.out.println("当前类每个测试方法(@Test)之后运行@AfterMethod");
}
@BeforeGroups(value="group1")
public void beforeGroups(){
System.out.println("配置组配group1之前运行@BeforeGroups..................");
}
@AfterGroups(value="group1")
public void afterGroups(){
System.out.println("配置组配group1之后运行@AfterGroups..................");
}
@Test
public void test1(){
System.out.println("runnig com.testng.TestConfig.test1()");
}
@Test(groups="group1")
public void test2(){
System.out.println("runnig com.testng.TestConfig.test2()");
}
@Test(groups="group1")
public void test3(){
System.out.println("runnig com.testng.TestConfig.test3()");
}
}
- 自定义 TestNG 的 xml 配置文件(Maven 项目则将该文件创建在 resource 目录下):
<?xml version="1.0" encoding="UTF-8"?>
<!-- @BeforeSuite -->
<suite name="tester">
<!-- @BeforeTest -->
<test name="case1">
<classes>
<class name="study.testng.TestConfig" />
<class name="study.testng.TestHelloWorld" />
</classes>
</test>
<!-- @AfterTest -->
<!-- @BeforeTest -->
<test name="case2">
<classes>
<class name="study.testng.TestConfig" />
</classes>
</test>
<!-- @AfterTest -->
</suite>
<!-- @AfterSuite -->
- 执行结果:
测试套件(当前xml中<suite>标签)之前运行@BeforeSuite--------------------
测试用例(当前xml中<test>标签)之前运行@BeforeTest----------
当前类每个测试方法(@Test)之前运行@BeforeMethod
runnig com.testng.TestConfig.test1()
当前类每个测试方法(@Test)之后运行@AfterMethod
配置组配group1之前运行@BeforeGroups..................
当前类每个测试方法(@Test)之前运行@BeforeMethod
runnig com.testng.TestConfig.test2()
当前类每个测试方法(@Test)之后运行@AfterMethod
当前类每个测试方法(@Test)之前运行@BeforeMethod
runnig com.testng.TestConfig.test3()
当前类每个测试方法(@Test)之后运行@AfterMethod
Hello World!
配置组配group1之后运行@AfterGroups..................
测试用例(当前xml中<test>标签)之后运行@AfterTest----------
测试用例(当前xml中<test>标签)之前运行@BeforeTest----------
当前类每个测试方法(@Test)之前运行@BeforeMethod
runnig com.testng.TestConfig.test1()
当前类每个测试方法(@Test)之后运行@AfterMethod
配置组配group1之前运行@BeforeGroups..................
当前类每个测试方法(@Test)之前运行@BeforeMethod
runnig com.testng.TestConfig.test2()
当前类每个测试方法(@Test)之后运行@AfterMethod
当前类每个测试方法(@Test)之前运行@BeforeMethod
runnig com.testng.TestConfig.test3()
当前类每个测试方法(@Test)之后运行@AfterMethod
配置组配group1之后运行@AfterGroups..................
测试用例(当前xml中<test>标签)之后运行@AfterTest----------
测试套件(当前xml中<suite>标签)之后运行@AfterSuite--------------------
从这个结果显示出注释的作用位置。其中 @BeforeGroups 和 @AfterGroups 的作用范围是可以跨类的,但类必须是在同一个测试用例(xml 中的 <test> 标签)范围内。
这些标签的执行顺序可以总结为:
@BeforeSuite -> @BeforeTest -> @BeforeClass -> {@BeforeMethod -> @Test -> @AfterMethod} -> @AfterClass -> @AfterTest -> @AfterSuite
(其中 {} 内的与多少个 @Test,就循环执行多少次)
配置文件结构
<?xml version="1.0" encoding="UTF-8"?>
<!--添加dtd约束文件,标签自动提示-->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite>
<suite-files>
<suite-file path=""></suite-file>
</suite-files>
<parameter name="" value=""></parameter>
<method-selectors>
<method-selector>
<selector-calss name=""></selector-calss>
</mehod-selector>
</method-selectors>
<test name="">
<parameter name="" value=""><parameter>
<groups>
<define name="">
<include name=""/>
<exclude name=""/>
</define>
<run>
<include name=""/>
<exclude name=""/>
</run>
</groups>
<classes>
<class name="">
<mehods>
<parameter name="" value=""></parameter>
<include name=""></include>
<exclude name=""></exclude>
</methods>
</class>
<class></class>
</classes>
<packages>
<package name="">
<include name=""></include>
<exclude name=""></exclude>
</package>
</packages>
<listeners>
<listener class-name=""/>
</listenters>
</test>
<test></test>
</suite>
配置文件标签说明
suite 标签
说明:一个 xml 文件只能有一个 <suite>, 是一个 xml 文件的根级。
<suite> 由 <test> 和 <parameters> 组成。
标签属性说明:
属性 | 说明 | 使用方法 | 参数值 |
---|---|---|---|
name | 名字,将出现在 reports 里 | name="XXX" | suite 名字 |
junit | 是否执行 Junit 模式(识别 setup() 等) | junit="true" | 默认 false |
verbose | 控制台输出的详细内容等级:0-10 级(0 无,10 最详细) | verbose="5" | 0 到 10 |
parallel | 是否在不同的线程并行进行测试,要与 thread-count 配套使用 | parallel="mehods" | (详见下文)默认 false |
parent-module | 和 Guice 框架有关,只运行一次,创建一个 parent injector 给所有 guice injectors | ||
guice-stage | 和 Guice 框架有关 | guice-stage="DEVELOPMENT" | 值有 DEVELOPMENT、PRODUCTION、TOOL,默认 "DEVELOPMENT" |
configfailurepolicy | 测试失败后是再次执行还是跳过 | configfailurepolicy="skip" | 值有 skip、continue,默认 "skip" |
thread-count | 与 parallel 配套使用,线程池的大小,决定并行线程数量 | thread-count="10" | 整数,默认 5 |
annotations | 获取注解,值为 javadoc 时,使用 JavaDoc 的注释;否则用 JDK5 注释 | annotations="javadoc" | javadoc |
time-out | 设置parallel时,终止执行单元之前的等待时间(毫秒) | time-out="10000" | 整数,单位毫秒 |
skipfailedinvocationcounts | 是否跳过失败的调用 | skipfailedinvocationcounts="true" | 默认 false |
data-provider-thread-count | 并发时 data-provider 的线程池数量 | data-provider-thread-count="5" | 整数 |
object-factory | 一个实现 IObjectFactory 接口的类,实例化测试对象 | object-factory="classname" | 类名 |
allow-return-values | 是否允许返回函数值 | all-return-values="true" | 默认 false |
preserve-order | 是否按照排序执行 | preserve-order="true" | 默认 true |
group-by-instances | 按照实例分组 | group-by-instances="true" | 默认 false |
parallel 属性详细说明:
- 该参数的值有 false、methods、tests、classes、instances,默认 false。
- parallel 必须和
thread-count
配套使用,否则相当于无效参数,thread-count 决定了并行测试时开启的线程数量。 parallel="mehods"
:TestNG 将并行执行所有的测试方法在不同的线程里。parallel="tests"
:TestNG 将并行执行在同一个 <test> 下的所有方法在不同线程里。parallel="classes"
:TestNG 将并行执行在相同 <class> 下的方法在不同线程里。parallel="instances"
:TestNG 将并行执行相同实例下的所有方法在不同的线程里。- parent-module 和 guice-stage 和 Guice 框架有关,testNG 6 对 Guice 框架提供了支持。
suite-files 标签
说明:引入外部的 xml 文件(地址由 path 参数决定,path 必填项),将引入的 xml 与当前的 xml 文件一起使用。
声明方法:
<suite-files>
<suite-file path="/path/suitefile1"></suite-file>
</suite-files>
test 标签
说明:一个 <suite> 下可以有多个 <test>,可以通过 <suite> 的 parallel="tests" 来进行并行测试,parallel 必须和 thread-count 配套使用,否则是无效参数。
<test> 由 <parameters>、<groups>、<classes> 三部分组成。
标签属性说明:
参数 | 说明 | 使用方法 | 参数值 |
---|---|---|---|
name | test(测试单元)的名字,将出现在报告里 | name="testname" | |
junit | 是否按照 Junit 模式运行 | junit="true" | 默认 false |
verbose | 控制台输出的详细内容等级,0-10 级(0 无,10 最详细),不在报告显示 | verbose="5" | 0 到 10 |
parallel | 是否在不同的线程并行进行测试,要与 thread-count 配套使用 | parallel="mehods" | 与 suite 的 parallel一致,默认 false |
thread-count | 与 parallel 配套使用,线程池的大小,决定并行线程数量 | thread-count="10" | 整数,默认 5 |
annotations | 获取注解,值为 javadoc 时,使用 JavaDoc 的注释;否则用 JDK5 注释 | annotations="javadoc" | javadoc |
time-out | 设置 parallel 时,终止执行单元之前的等待时间(毫秒) | time-out="10000" | 整数,单位毫秒 |
enabled | 标记是否执行这个 test | enabled="true" | 默认 true |
skipfailedinvocationcounts | 是否跳过失败的调用 | skipfailedinvocationcounts="true" | 默认 false |
preserve-order | 是否按照排序执行。如果是 true,将按照 xml 文件中的顺序去执行 | preserve-order="true" | 默认 true |
allow-return-values | 是否允许返回函数值 | all-return-values="true" | 默认 false |
parameter 标签
说明:提供测试数据,有 name 和 value 两个参数。
声明方法:
<parameter name = "parameter_name" value = "parameter_value "/>
testng.xml 文件中的 <parameter> 可以声明在 <suite> 或者 <test> 级别,在 <test> 下的 <parameter> 会覆盖在 <suite> 下声明的同名变量。
groups 标签
说明:要运行的组。可以自定义一个组,定义要执行的和要排除的方法。必须和 <classes> 配套使用,从其下的类中找到对应名字的方法。
<groups> 由 <difine> 和 <run>、<dependencies> 三部分组成:
<diffine>
:可以将 group 组成一个新组,包括要执行和不执行的大组。<run>
:要执行的方法。<dependencies>
:指定了某 group 需要依赖的 group(比如下面的例子,group1 需要依赖 group2 和 group3 先执行)。
声明方法:
<suite name = "TestNG Suite">
<test name = "Grouping">
<groups>
<define name = "All"> <!-- 定义新的分组 -->
<include name = "动物" /> <!-- 测试类中的分组名 -->
<include name = "人" />
</define>
<run>
<include name = "All" /> <!-- 本测试单元执行新定义的分组 -->
</run>
<dependencies>
<group name ="group1" depends-on="goup2 group3"/>
</dependencies>
</groups>
<classes>
<class name = "com.group"/> <!-- 测试程序的全类名 -->
</classes>
</test>
</suite>
classes 标签
说明:方法选择器,要执行的方法写在这里,参数有 name 和 priority。
- <classes> 下必须写要执行的 <class>,否则不会执行任何内容。如果填写了 class 没有写 methods,会按照填写的 class 的下的注释 @Test 去执行所有的方法。
- <classes> 下的 <methods> 如果填写了 <include>,那么只会执行所填写的方法,没有填写的方法不会去执行。
声明方法:
<classes>
<class name="要执行的class名">
<methods>
<include name="要执行的方法名"></include>
</methods>
</class>
</classes>
TestNG 参数化
@Parameters
案例:使用 @Parameters 注解从测试配置 xml 文件获取参数
- 创建测试类:PatamterTest.java
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
/**
* testNG的参数化配置,通过xml文件进行方法的赋值操作
*/
public class PatamterTest {
@Test
@Parameters({"name","age"})
public void showInfo(String name, int 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" >
<suite name="paramterTest">
<test name="transfer">
<classes>
<class name="com.testng.paramter.PatamterTest"/>
<parameter name="name" value="张三"/>
<parameter name="age" value="11"/>
</classes>
</test>
</suite>
-
- 运行结果:
name=张三 age=11
注意:在配置文件中如果定义了多个重名的 parameter,那么后定义的参数值会覆盖前面的。
@DataProvider
使用步骤:
- 定义一个数据源的方法,通过
@DataProvider
注解来标识。 - 定义一个测试方法,通过
@Test(dataProvider="")
属性来获取数据。
示例:
package com.testng;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DataProviderTest {
/**
* 数据源,是方法提供数据,返回必须是一个二维数组
* @DataProvider(name="data") 通过该注解来标识这个为数据源,name为数据源的名称。
* @return 返回一个二维数组
*/
@DataProvider(name="data")
public Object[][] providerData() {
Object[][] data = new Object[][] {
{"zhangsan", 12},
{"lisi", 22},
{"wangwu", 32}
};
return data;
}
/**
* 通过dataProvider来获取数据,执行的次数会根据数据源提供数据的数量
* 例如上面的二维数组长度为3,则该方法会执行三次。
* @param name
* @param age
*/
@Test(dataProvider="data")
public void testDataProvider(String name, int age) {
System.out.println("name=" + name + " age=" + age);
}
}
运行结果:
name=zhangsan age=12
name=lisi age=22
name=wangwu age=32
TestNG 多线程测试
注解方式
invocationCount
:线程调用的次数(默认 1 次)。threadPoolSize
:线程池大小,和 invocationCount 一起使用。如果没有定义 invocationCount 是没有效果的。
示例:
import org.testng.annotations.Test;
public class MultiThreadOnAnnotion {
/**
* 表示开启3个线程,共执行该方法10次
*/
@Test(invocationCount=10, threadPoolSize=3)
public void test(){
System.out.printf("Thread Id : %s%n", Thread.currentThread().getId());
}
}
执行结果:
Thread Id : 11
Thread Id : 12
Thread Id : 13
Thread Id : 13
Thread Id : 13
Thread Id : 13
Thread Id : 11
Thread Id : 12
Thread Id : 13
Thread Id : 12
xml 配置方式
- 创建测试类:
import org.testng.annotations.Test;
/**
* 使用配置文件来实现testng的多线程
*/
public class MultiThreadOnXml {
@Test
public void test1() {
System.out.printf("Thread id: %s%n", Thread.currentThread().getId());
}
@Test
public void test2() {
System.out.printf("Thread id: %s%n", Thread.currentThread().getId());
}
@Test
public void test3() {
System.out.printf("Thread id: %s%n", Thread.currentThread().getId());
}
@Test
public void test4() {
System.out.printf("Thread id: %s%n", Thread.currentThread().getId());
}
}
- 创建配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="thread" parallel="methods" thread-count="3">
<!--
parallel:
tests级别:不同的 test tag 下的用例可以在不同的线程下执行
相同的 test tag 下的用例只能在同一个线程中去执行
classs级别:不同的 class tag 下的用例可以在不同的线程中执行
相同的 class tag 下的用例在同一个线程中执行
methods级别:所有用例都可以在不同的线程下去执行
thread-count:代表了最大并发线程数
xml文件配置这种方式不能指定线程池,只有方法上才可以指定线程池
-->
<test name="test1">
<classes>
<class name="com.testng.MultiThreadOnXml"/>
</classes>
</test>
</suite>
- 执行结果:
Thread id: 12
Thread id: 13
Thread id: 11
Thread id: 12