1.介绍
TestNG是一个设计用来简化广泛的测试需求的Java测试框架,从单元测试(隔离测试一个类)到集成测试,自动生成测试报告。
2.使用
使用IDEA创建Maven工程,并在pom.xml中添加:
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
</dependency>
</dependencies>
3.基本注解
注解 | 描述 |
---|---|
@Test | 标记一个类或方法作为测试的一部分 |
@BeforeMethod | 被注释的方法将在每一个测试方法调用前运行 |
@AfterMethod | 被注释的方法将在每一个测试方法调用后运行 |
@BeforeClass | 在调用当前类的第一个测试方法之前运行,仅运行一次 |
@AfterClass | 在调用当前类的最后一个测试方法之后运行,仅运行一次 |
@BeforeTest | 将会在所有的测试方法执行之前运行 |
@AfterTest | 将会在所有的测试方法执行之后运行 |
@BeforeSuite | 在该套件的所有测试都运行在注释的方法之前,仅运行一次 |
@AfterSuite | 在该套件的所有测试都运行在注释方法之后,仅运行一次 |
@BeforeGroups | 配置方法将在之前运行组列表。 在调用属于这些组中的任何一个的第一个测试方法之前不久运行。 |
@AfterGroups | 此配置方法将在之后运行组列表。在调用属于任何这些组的最后一个测试方法之后不久运行。 |
@DataProvider | 标记一个方法用于为测试方法提供数据。 被注释的方法必须返回Object[][] ,其中每个Object[] 可以指派为这个测试方法的参数列表 |
@Parameters | 传递参数给@Test方法 |
注意:必须掌握注解的执行顺序
- Before开头的注解,一般用于初始化环境、 准备测试环境(初始化、数据准备等)
- After开头的注解,一般用于执行测试的环境清理工作(退出、关闭资源等)
举个例子,假设要测试微信功能:1.语音通话 2.视频通话
步骤:
手机解锁 @BeforeSuite
打开微信 @BeforeTest
打开好友聊天界面 @BeforeClass
邀请通话 @BeforeMethod //会执行2次,邀请语音,邀请视频
语音通话 @Test
视频通话 @Test
挂断通话 @AfterMethod //会执行2次,挂断语音,挂断视频
回到微信主屏(退出聊天界面) @AfterClass
关闭微信 @AfterTest
手机锁屏 @AfterSuite
4.测试套件
测试套件是为了测试软件程序的行为或一系列行为, 是一个集合。
在TestNG中, 使用xml文件来进行测试套件的配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="套件名">
<test name="测试名">
<classes>
<class name="com.testng" />
</classes>
</test>
</suite>
常用标签层级关系:
|-- suite //只能一个,name必填
|-- test //可以多个,name必填
|-- classes
|-- class
|-- methods
|-- groups
|-- run
|-- include
|-- exclude
|-- packages
|-- package
5.分组测试
5.1方法分组
@Test(groups = "apple")
public void apple1(){
System.out.println("拿第1个苹果");
}
@Test(groups = "apple")
public void apple2(){
System.out.println("拿第2个苹果");
}
@Test
public void banana(){
System.out.println("拿香蕉");
}
@BeforeGroups("apple")
public void beforeApple(){
System.out.println("拿苹果之前运行");
}
@AfterGroups("apple")
public void afterApple(){
System.out.println("拿苹果之后运行");
}
运行类,结果:
拿苹果之前运行
拿第1个苹果
拿第2个苹果
拿苹果之后运行
拿香蕉
===============================================
Default Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
5.2类分组
新建一个包com.testng.groups
,在包下分别创建3个类:
Student1.class
在类上用@Test(groups="stu")
归类为stu组Student2.class在
类上用@Test(groups="stu")
归类为stu组Teacher.class
在类上用@Test(groups="teacher")
归类为teacher组
新建一个groups.xml
文件,内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="groupsTest">
<test name="runAll"> <!-- 运行groups包下所有的测试方法 -->
<packages>
<package name="com.testng.groups"></package>
</packages>
</test>
<test name="onlyStudent"> <!-- 只运行类是stu组下所有的测试方法 -->
<groups>
<run>
<include name="stu"/>
</run>
</groups>
<packages>
<package name="com.testng.groups"></package>
</packages>
</test>
</suite>
<test name="runAll">
的执行结果:运行所有类中的测试方法
<test name="onlyStudent">
的执行结果:只运行类为stu
组的方法
6.依赖测试
6.1 依赖方法
用法:
@Test
public void initMethod(){
System.out.println("初始化方法");
}
@Test(dependsOnMethods = {"initMethod"})
public void action(){
System.out.println("执行的方法");
}
执行action()
方法,将先执行initMethod()
方法,结果如下:
初始化方法
执行的方法
===============================================
Default Suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================
注意:
- 若
initMethod()
方法执行失败,后续方法将会被忽略。 - 只有被依赖的方法,即
initMethod()
执行成功,才会运行下一个测试用例。
6.2 依赖组
用法:
@Test(groups = "聊天前置")
public void login(){
System.out.println("登录QQ");
}
@Test(groups = "聊天前置")
public void findFriend() {
System.out.println("找到好友:小明");
}
@Test(dependsOnGroups = "聊天前置")
public void chat(){
System.out.println("和小明愉快的聊天");
}
运行chat()
方法,打印结果:
登录QQ
找到好友:小明
和小明愉快的聊天
===============================================
Default Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
7.参数化测试
TestNG提供了2种传递参数的方式:
testng.xml
方式,使代码和测试数据分离,方便维护@DataProvider
能够提供比较复杂的参数。(也叫data-driven testing,简称:DDT)
7.1 xml中定义参数
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="parameter">
<test name="param">
<parameter name="name" value="zhangsan"/> <!-- 定义name=zhangsan -->
<parameter name="age" value="20"/> <!-- 定义age=20 -->
<classes>
<class name="com.testng.BaseAnnotation">
<methods>
<include name="testCase4" />
</methods>
</class>
</classes>
</test>
</suite>
注意:parameter
标签的name
要唯一,否则会被覆盖(即谁在后面用谁)
测试方法:
@Test
@Parameters({"name", "age"}) // 注意此处一定要加上
public void testCase4(String name, int age){
System.out.println("姓名:"+name+";年龄:"+age);
}
打印结果:
姓名:zhangsan;年龄:20
===============================================
parameter
Total tests run: 1, Failures: 0, Skips: 0
===============================================
7.2 使用@DataProvider
@DataProvider
提供数据的方法:
@DataProvider //提供数据的方法
public Object[][] Users(){
return new Object[][]{
{ "zhangsan", 20 },
{ "lisi", 18 },
{ "wangwu", 40 }
};
}
@Test(dataProvider = "Users") //使用数据
public void testCase2(String name, int age){
System.out.println("姓名:"+name+";年龄:"+age);
}
打印结果:
姓名:zhangsan;年龄:20
姓名:lisi;年龄:18
姓名:wangwu;年龄:40
===============================================
Default Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
8.忽略测试
用法:@Test(enabled=false)
适用场景:测试用例还没开发完成时,需要跳过某个测试方法。
9.异常测试
适用场景:实际测试中,预期是程序抛出异常。下方代码块预期抛出RuntimeException
异常:
@Test(expectedExceptions = RuntimeException.class)
public void testCase3(){
System.out.println("预期程序抛出RuntimeException异常");
throw new RuntimeException(); //如果没有这行代码,TestNG的运行结果将会是failed
}
10.执行顺序
10.1 默认执行顺序
同一个类中的@Test
测试方法,默认按方法名字母排序来执行,如:
无论写的顺序如何,apple()
将会在方法banana()
之前运行。
10.2 自定义执行顺序
适用场景:当需要指定测试方法运行顺序时,可以通过priority
属性来自定义。
用法:@Test(priority = 0)
@Test(priority = 1)
priority
的数值为0时最先执行,数值越大,执行优先级别越低(越后执行)。