testNG笔记
一、TestNG介绍
TestNG是一个来自JUnit和NUnit的测试框架,它具拥有更多的功能,提高了执行的效率。并且是一个开源的自动化测试框架
TestNG去除了老框架的大部分限制,借助于简单的注释、分组、排序和参数化这些功能。使脚本开发人员能够编写更灵活、更强大的测试用例脚本。
1、TestNG的主要优点是:
•可以生成日志
•注释使代码高效且易于管理
•能够生成执行的HTML报告
•测试用例可以分组并按优先级排序
•可以实现并行测试
•可以实现数据参数化
2、TestNG的注解:
@BeforeSuite:
使用这个注解的方法会在test suite中的所有test运行之前运行
@AfterSuite:
使用这个注解的方法会在test suite中的所有test运行之后运行
@BeforeTest:
使用这个注解的方法会在xml文件中的test标签中的每个test方法运行之前运行
@AfterTest:
使用这个注解的方法会在xml文件中的test标签中的每个test方法运行之后运行
@BeforeClass:
使用这个注解的方法会在当前这个类的第一个test方法运行之前运行
@AfterClass:
使用这个注解的方法会在当前这个类的最后一个test方法运行之后运行
@BeforeMethod:
使用这个注解的方法会在每个test方法运行之前运行。
@AfterMethod:
使用这个注解的方法会在每个test方法运行之后运行。
@Test:
使用这个注解的方法就是我们要执行的测试用例的代码
3、使用注解的好处:
1.TestNG通过查找注解来标识对应的方法。所以不依赖于方法名来识别
2.我们可以将参数传递给注解。
3.注解是强类型的,所以有任何错误编译器会立即给出提示。
4.测试类不再需要扩展任何东西(例如,JUnit 3的测试用例)
注意点:
TestNG的注解(@BeforeSuite和@AfterSuite、@BeforeTest和@AfterTest)不能直接在类中右键testNG执行,只能通过XML文件右键testNG执行。
测试用例分别执行,每一个用例都是单独的。
1、测试方法分优先级执行:priority
@Test(priority = 2)
public void testMethod1() {
System.out.println("TestNG_Prioritiy->testMethod1");
}
@Test(priority = 1)
public void testMethod2() {
System.out.println("TestNG_Prioritiy->testMethod2");
}
@Test(priority = 0)
public void testMethod3() {
System.out.println("TestNG_Prioritiy->testMethod3");
}
执行结果:
2、如何给测试方法分组执行:groups
// alwaysRun = true 就会设置BeforeClass在类中测试方法之前执行,可以解决设置分组后注解@BeforeClass和@AfterClass不执行
@BeforeClass(alwaysRun = true)
public void setUp() {
System.out.println("BeforeClass");
}
// groups={"分组名称"}
@Test(groups = { "cars", "suv" })
public void testBMWX6() {
System.out.println("Running Test - BMW X6");
}
XML文件格式:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Regression TestSuite">
<test name="GroupsDemo">
<!--testNG注释:给测试方法分组执行,使用xml进行分组,如下格式执行 -->
<groups>
<!-- define:name自己起的名字 -->
<define name="all">
<!-- include:name需要和testNGClass包中的类名字要一致 -->
<include name="suv"></include>
<include name="bike"></include>
<include name="sedan"></include>
</define>
<define name="nobike">
<include name="suv"></include>
<include name="sedan"></include>
</define>
<!-- run:运行分组,根据name的名字执行,只跑想跑的组 -->
<run>
<!-- name对应的分组名称 -->
<include name="all"></include>
</run>
</groups>
<classes>
<!-- name格式:包名.类名 -->
<class name="testNGClass.testNG_Grouping">
</class>
</classes>
</test>
</suite>
注意点:testNG之XML文件注释格式:<!--注释的内容 -->
3、测试用例的依赖关系:dependsOnMethods
// dependsOnMethods测试用例的依赖关系,使用alwaysRun = true testMethod2不执行,testMethod1也会执行
@Test(dependsOnMethods = { "testMethod2" }, alwaysRun = true)
public void testMethod1() {
System.out.println("testMethdo1");
}
@Test
public void testMethod2() {
System.out.println("testMethdo2");
// 声明一个int变量接收这个方法的结果
int result = obj.add(1, 2);
Assert.assertEquals(result, 3);
}
@Test(dependsOnMethods = { "testMethod1" })
public void testMethod3() {
System.out.println("testMethod3");
}
4、禁用测试方法或者让测试方法失效:enabled、timeOut
// Test属性:enabled = false 禁用该方法
// Test属性:enabled = true 默认使用该方法
@Test(enabled = false)
public void testMethod1() {
System.out.println("testMethod1");
}
// Test属性:timeOut定义超时时间
@Test(timeOut = 100)
public void testMethod2() throws InterruptedException {
System.out.println("testMethod2");
Thread.sleep(200);
}
5、维持测试用例的执行顺序:preserve、enabled
<!-- 维持测试用例的执行顺序 -->
<suite name="Preserve Enable TestSuite">
<!--test标签属性:preserve-order="false"解释:不是按照class标签顺序执行 -->
<!-- test标签属性:preserve-order="true"解释:按照class标签顺序之前 -->
<test name="Test 1" preserve-order="false">
<classes>
<class name="testNGClass.TestNG_Preserver1"></class>
<class name="testNGClass.TestNG_Preserver2"></class>
</classes>
</test>
<!-- suite中支持多个test,如果不想执行其中一个test可以把属性添加:enabled="false" ,属性默认为enabled="true"-->
<test name="Test 2" enabled="true" >
<classes>
<class name="testNGClass.TestNG_Preserver1"></class>
<class name="testNGClass.TestNG_Preserver2"></class>
</classes>
</test>
</suite>
6、读取XML文件中的参数:Parameters
备注:
1、XML文件中parameter value:必须是字符串
2、只能使用XML执行类
public class TestNG_Parameters {
@BeforeClass
@Parameters({ "browser", "platform" })
public void setUp(String browser, String platform) {
System.out.println("TestNG_Parameters->Setup");
System.out.println("1.Parameter value from xml file:" + browser);
System.out.println("2.Parameter value from xml file:" + platform);
}
@Test
@Parameters({ "response" })
public void testMethod1(String response) {
String[] stringArray = response.split(",");
System.out.println("TestNG_Parameters->testMethod1");
System.out.println("Response from xml file:" + response);
System.out.println("StringArry[0] from xml file:" + stringArray[0]);
System.out.println("StringArry[1] from xml file:" + stringArray[1]);
}
}
XML
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Parameters TestSuite">
<test name="Test 1">
<!--读取XML中的参数parameter -->
<parameter name="browser" value="firefox"></parameter>
<parameter name="platform" value="windows"></parameter>
<parameter name="response" value="201,200"></parameter>
<classes>
<class name="testNGClass.TestNG_Parameters"></class>
</classes>
</test>
</suite>
7、用testNG并行执行case:parallel="值"
常用值:tests、classes、methods
并发线程数:thread-count="值",5,4,3,2,1,根据自己电脑配置设置。
备注:tests和classes,不同的test并行执行;methods是类中的方法同时并行执行。
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<!-- 用testNG并行执行case,属性parallel ,并发线程thread-count-->
<suite name="Parallel TestSuite" parallel="tests" thread-count="2">
<test name="Test 1">
<classes>
<class name="testNGClass.TestNG_Parallel1">
</class>
</classes>
</test>
<test name="Test 2">
<classes>
<class name="testNGClass.TestNG_Parallel2">
</class>
</classes>
</test>
</suite>
8、一个测试方法多个参数:dataproviders
单个数据:
public class TestNG_DataProviders {
@DataProvider(name = "inputs")
public Object[][] getData() {
return new Object[][] { { "Apple", "red" }, { "WaterMelon", "green" }, { "Orange", "yellow" }
};
}
/* 一个测试方法多个参数 */
@Test(dataProvider = "inputs")
public void testMethod1(String input1, String input2) {
System.out.println("input1:" + input1);
System.out.println("input2:" + input2);
}
}
多个数据
public class TestNG_DataProviders {
/*
* @DataProvider(name = "inputs") public Object[][] getData() { return new
* Object[][] { { "Apple", "red" }, { "WaterMelon", "green" }, { "Orange",
* "yellow" }
*
* };
*
* }
*/
/* 一个测试方法多个参数 */
/*
* dataProviderClass = 对应的数据类(格式:①同一个包内,类名.class②不在一个包内,包名.类名.class),
* 测试方法和测试数据分离,因为在同一个包中不需要导入包,如果不在一个包内需要导入包
*/
@Test(dataProvider = "inputs", dataProviderClass = TestData.class)
public void testMethod1(String input1, String input2) {
System.out.println("input1:" + input1);
System.out.println("input2:" + input2);
}
}
9、ITestResult接口:监听器,test方法执行完成后,可以知道执行结果
public class TestNG_ITestResultDmeo {
@Test
public void testMethod1() {
System.out.println("Running --> testMethod1");
// 断言是否为真,结果是false
Assert.assertTrue(false);
}
@Test
public void testMethod2() {
System.out.println("Running --> testMethod2");
// 断言是否为真,结果是true
Assert.assertTrue(true);
}
@AfterMethod
public void afterMethod(ITestResult testresult) {
// getStatus()执行结果的状态
if (testresult.getStatus() == ITestResult.FAILURE) {
// getMethod哪一个测试方法,getMethodName哪一个测试方法的名字
System.out.println("Failed" + testresult.getMethod().getMethodName());
}
if (testresult.getStatus() == ITestResult.SUCCESS) {
// getName()方法:返回的是测试方法的名字
System.out.println("Successful" + testresult.getName());
}
}
}
10、理解事件监听机制:
(1)、IInvokedMethodListener
普通类:
备注:implements 引用接口
public class CutomerListener1 implements IInvokedMethodListener {
@Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
// 在测试类里的每一个方法运行之前跑
System.out.println("before Invocation:" + testResult.getClass().getName() + "-->"
+ method.getTestMethod().getMethodName());
}
@Override
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
// 在测试类里的每一个方法运行之后跑
System.out.println("before Invocation:" + testResult.getClass().getName() + "-->"
+ method.getTestMethod().getMethodName());
}
}
(2)、ITestListener
普通类:
public class CustomerListener2 implements ITestListener {
@Override
public void onFinish(ITestContext arg0) {
// 在XML文件的Test标签执行之后执行,getName()test标签的名字
System.out.println("onFinish-->test tag name:" + arg0.getName());
}
@Override
public void onStart(ITestContext arg0) {
// 在XML文件的Test标签执行之前执行,getName()test标签的名字
System.out.println("onStart-->test tag name:" + arg0.getName());
ITestNGMethod methods[] = arg0.getAllTestMethods();
System.out.println("test标签里面要执行的测试方法");
for (ITestNGMethod method : methods) {
System.out.println(method.getMethodName());
}
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
// 执行5个case正确4个才执行此方法,用处不大,可以忽略
}
@Override
public void onTestFailure(ITestResult arg0) {
// 如果测试方法失败才执行此方法
System.out.println("onTestFailure-->test name:" + arg0.getName());
}
@Override
public void onTestSkipped(ITestResult arg0) {
// 如果测试方法跳过时才执行此方法
System.out.println("onTestSkipped-->test name:" + arg0.getName());
}
@Override
public void onTestStart(ITestResult arg0) {
// 测试方法开始时才执行此方法
System.out.println("onTestStart-->test name:" + arg0.getName());
}
@Override
public void onTestSuccess(ITestResult arg0) {
// 如果测试方法成功才执行此方法
System.out.println("onTestSuccess-->test name:" + arg0.getName());
}
}
testNG测试类:
//使用事件监听关键字
@Listeners(CustomerListener2.class)
public class TestNG_ListenersTest2 {
@BeforeClass
public void setUp() {
System.out.println("Code in Before Class");
}
@AfterClass
public void cleanUp() {
System.out.println("Code in After Class");
}
@Test
public void testMethod1() {
System.out.println("Conde in testMethod1");
Assert.assertTrue(true);
}
@Test
public void testMethod2() {
System.out.println("Code in testMethod2");
Assert.assertTrue(false);
}
}
(3)、ISuiteListener:
XML
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<!-- IInoedMethodListener,case执行:成功、失败、跳过等事件 -->
<suite name="Listeners TestSuite">
<!-- ISuiteListener监听器,listeners标签, -->
<listeners>
<!-- class-name="包名.普通类名" -->
<listener class-name="listenerspackage.CustomerListener3"></listener>
</listeners>
<test name="Application Test1">
<classes>
<class name="testNGClass.TestNG_ListenersTest3"></class>
</classes>
</test>
<test name="Application Test2">
<classes>
<class name="testNGClass.TestNG_ListenersTest4"></class>
</classes>
</test>
</suite>
testNGClass类方:TestNG_ListenersTest3&TestNG_ListenersTest4一样
public class TestNG_ListenersTest3 {
@BeforeClass
public void setUp() {
System.out.println("Code in Before Class");
}
@AfterClass
public void cleanUp() {
System.out.println("Code in After Class");
}
@Test
public void testMethod1() {
System.out.println("TestNG_ListenersTest3-->Conde in testMethod1");
Assert.assertTrue(true);
}
@Test
public void testMethod2() {
System.out.println("TestNG_ListenersTest3-->Code in testMethod2");
Assert.assertTrue(false);
}
}
11、testNG监听器代码重构:IInvokedMethodListener, ITestListener, ISuiteListener合并在一起
普通类:
//testNG监听器代码重构:三个监听器合并到一个类中使用
public class CustomerListenerAll implements IInvokedMethodListener, ITestListener, ISuiteListener {
//-------------------------------------------------------------IInvokedMethodListener
// test类中所有方法执行之前都会执行beforeInvocation
@Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
// 在测试类里的每一个方法运行之前跑
System.out.println("before Invocation:" + testResult.getClass().getName() + "-->"
+ method.getTestMethod().getMethodName());
}
@Override
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
// 在测试类里的每一个方法运行之后跑
System.out.println("before Invocation:" + testResult.getClass().getName() + "-->"
+ method.getTestMethod().getMethodName());
}
//-------------------------------------------------------------ITestListener
@Override
public void onFinish(ITestContext arg0) {
// 在XML文件的Test标签执行之后执行,getName()test标签的名字
System.out.println("onFinish-->test tag name:" + arg0.getName());
}
@Override
public void onStart(ITestContext arg0) {
// 在XML文件的Test标签执行之前执行,getName()test标签的名字
System.out.println("onStart-->test tag name:" + arg0.getName());
ITestNGMethod methods[] = arg0.getAllTestMethods();
System.out.println("test标签里面要执行的测试方法");
for (ITestNGMethod method : methods) {
System.out.println(method.getMethodName());
}
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
// 执行5个case正确4个才执行此方法,用处不大,可以忽略
}
@Override
public void onTestFailure(ITestResult arg0) {
// 如果测试方法失败才执行此方法
System.out.println("onTestFailure-->test name:" + arg0.getName());
}
@Override
public void onTestSkipped(ITestResult arg0) {
// 如果测试方法跳过时才执行此方法
System.out.println("onTestSkipped-->test name:" + arg0.getName());
}
@Override
public void onTestStart(ITestResult arg0) {
// 测试方法开始时才执行此方法
System.out.println("onTestStart-->test name:" + arg0.getName());
}
@Override
public void onTestSuccess(ITestResult arg0) {
// 如果测试方法成功才执行此方法
System.out.println("onTestSuccess-->test name:" + arg0.getName());
}
//-------------------------------------------------------------ISuiteListener
@Override
public void onFinish(ISuite arg0) {
// 当suite标签执行完后执行
System.out.println("onFinish:suite 开始执行之后");
}
@Override
public void onStart(ISuite arg0) {
// 当suite标签执行开始时执行
System.out.println("onStart:suite 开始执行之前");
}
}
XML
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<!-- IInoedMethodListener,case执行:成功、失败、跳过等事件 -->
<suite name="Listeners TestSuite">
<!-- ISuiteListener监听器,listeners标签, -->
<listeners>
<!-- class-name="包名.普通类名" -->
<listener class-name="listenerspackage.CustomerListenerAll"></listener>
</listeners>
<test name="Application Test1">
<classes>
<class name="testNGClass.TestNG_ListenersTest3"></class>
</classes>
</test>
<test name="Application Test2">
<classes>
<class name="testNGClass.TestNG_ListenersTest4"></class>
</classes>
</test>
</suite>
12、TestNG报告和日志:reporter
public class TestNG_ReportsAndLogs {
@BeforeClass
public void setUp() {
// System.out.println("TestNG_ReportsAndLogs --> 在class开始运行之前运行");
// log(string,boolean),true Console输出,false Console不输出
Reporter.log("TestNG_ReportsAndLogs --> BeforeClass -->在class开始运行之前运行", true);
}
@AfterClass
public void cleanUp() {
// System.out.println("TestNG_ReportsAndLogs -->在class运行之后运行");
Reporter.log("TestNG_ReportsAndLogs --> AfterClass -->在class运行之后运行", true);
}
@BeforeMethod
public void beforeMethod() {
// System.out.println("TestNG_ReportsAndLogs -->每个test方法运行之前运行");
Reporter.log("TestNG_ReportsAndLogs --> BeforeMethod -->每个test方法运行之前运行", true);
}
@AfterMethod
public void afterMethod() {
// System.out.println("TestNG_ReportsAndLogs -->每个test方法运行之后运行");
Reporter.log("TestNG_ReportsAndLogs --> AfterMethod -->每个test方法运行之后运行", true);
}
//Success test
@Test
public void testMethod1() {
// System.out.println("TestNG_ReportAndLogs -->testMethod1");
Reporter.log("TestNG_ReportAndLogs --> Test -->testMethod1", true);
}
//Failures test
@Test
public void testMethod2() {
// System.out.println("TestNG_ReportAndLogs -->testMethod2");
Reporter.log("TestNG_ReportAndLogs -->Test -->testMethod2", true);
Assert.assertTrue(false);
}
//Skips test(dependsOnMethods={"testMethod2"}依赖)
@Test(dependsOnMethods = { "testMethod2" })
public void testMethod3() {
// System.out.println("TestNG_ReportAndLogs -->testMethod3");
Reporter.log("TestNG_ReportAndLogs -->Test -->testMethod3", true);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY