【bak】https://www.cnblogs.com/uncleyong/p/15855473.html
TestNG简介
单元测试框架,可以用来设计用例的执行流程
创建maven项目,添加依赖
<dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.14.3</version><scope>test</scope></dependency>
常用注解
@BeforeSuite / @AfterSuite
@BeforeTest / @AfterTest
@BeforeClass / @AfterClass,在类运行之前/后运行
@BeforeMethod / @AfterMethod,在测试方法之前/后运行
package com.qzcsbj;import org.testng.annotations.*;
import org.testng.annotations.Test;/*** @描述 : <...>* @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201*/
public class TestAnnotation {@Testpublic void test(){System.out.println("TestAnnotation.test");System.out.println("线程ID:" + Thread.currentThread().getId());}@Testpublic void test2(){System.out.println("TestAnnotation.test2");}@BeforeMethodpublic void beforeMethodTest(){System.out.println("TestAnnotation.beforeMethodTest");}@AfterMethodpublic void afterMethodTest(){System.out.println("TestAnnotation.afterMethodTest");}@BeforeClasspublic void beforeClassTest(){System.out.println("TestAnnotation.beforeClassTest");}@AfterClasspublic void afterClassTest(){System.out.println("TestAnnotation.afterClassTest");}@BeforeSuitepublic void beforeSuiteTest(){System.out.println("TestAnnotation.beforeSuiteTest");}@AfterSuitepublic void afterSuiteTest(){System.out.println("TestAnnotation.afterSuiteTest");}
}
输出结果:
TestAnnotation.beforeSuiteTest
TestAnnotation.beforeClassTest
TestAnnotation.beforeMethodTest
TestAnnotation.test
线程ID:1
TestAnnotation.afterMethodTest
TestAnnotation.beforeMethodTest
TestAnnotation.test2
TestAnnotation.afterMethodTest
TestAnnotation.afterClassTest
TestAnnotation.afterSuiteTest
安装插件Create TestNG XML
搜索:Create TestNG XML
安装
重启后
创建xml文件
在resources下创建suite.xml,文件名随意,只要内容符合要求就可以了
suite:套件,包含一个或多个test
test:测试集,包含一个或多个classes
classes:测试类集合,包含一个或多个class
class:测试类,包含一个或多个方法
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite"><!--<test verbose="2" preserve-order="true" name="test">--><test name="test"><classes><class name="com.qzcsbj.TestAnnotation"/></classes></test><test name="test2"><classes><class name="com.qzcsbj.TestAnnotationB"><methods><include name="testb"/> <!--指定要运行的方法--></methods></class></classes></test>
</suite>
套件测试
第一个类
package com.qzcsbj;import org.testng.annotations.*;
import org.testng.annotations.Test;/*** @描述 : <...>* @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201*/
public class TestAnnotation {@Testpublic void test(){System.out.println("TestAnnotation.test");System.out.println("线程ID:" + Thread.currentThread().getId());}@Testpublic void test2(){System.out.println("TestAnnotation.test2");}@BeforeMethodpublic void beforeMethodTest(){System.out.println("TestAnnotation.beforeMethodTest");}@AfterMethodpublic void afterMethodTest(){System.out.println("TestAnnotation.afterMethodTest");}@BeforeClasspublic void beforeClassTest(){System.out.println("TestAnnotation.beforeClassTest");}@AfterClasspublic void afterClassTest(){System.out.println("TestAnnotation.afterClassTest");}@BeforeSuitepublic void beforeSuiteTest(){System.out.println("TestAnnotation.beforeSuiteTest");}@AfterSuitepublic void afterSuiteTest(){System.out.println("TestAnnotation.afterSuiteTest");}
}
第二个类
package com.qzcsbj;import org.testng.annotations.*;
import org.testng.annotations.Test;/*** @描述 : <...>* @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201*/
public class TestAnnotationB {@Testpublic void testb(){System.out.println("TestAnnotation.testb==");System.out.println("线程ID:" + Thread.currentThread().getId());}@Testpublic void testb2(){System.out.println("TestAnnotationB.testb2==");}@BeforeMethodpublic void beforeMethodTestb(){System.out.println("TestAnnotationB.beforeMethodTestb==");}@AfterMethodpublic void afterMethodTestb(){System.out.println("TestAnnotationB.afterMethodTestb==");}@BeforeClasspublic void beforeClassTestb(){System.out.println("TestAnnotationB.beforeClassTestb==");}@AfterClasspublic void afterClassTestb(){System.out.println("TestAnnotationB.afterClassTestb==");}@BeforeSuitepublic void beforeSuiteTestb(){System.out.println("TestAnnotationB.beforeSuiteTestb==");}@AfterSuitepublic void afterSuiteTestb(){System.out.println("TestAnnotationB.afterSuiteTestb==");}
}
输出结果:
TestAnnotation.beforeSuiteTest
TestAnnotationB.beforeSuiteTestb==TestAnnotation.beforeClassTest
TestAnnotation.beforeMethodTest
TestAnnotation.test
线程ID:1
TestAnnotation.afterMethodTestTestAnnotation.beforeMethodTest
TestAnnotation.test2
TestAnnotation.afterMethodTest
TestAnnotation.afterClassTestTestAnnotationB.beforeClassTestb==
TestAnnotationB.beforeMethodTestb==
TestAnnotation.testb==
线程ID:1TestAnnotationB.afterMethodTestb==
TestAnnotationB.afterClassTestb==TestAnnotation.afterSuiteTest
TestAnnotationB.afterSuiteTestb==
忽略测试
测试过程中,问题还没解决,可以先忽略,也就是不执行此方法
package com.qzcsbj;import org.testng.annotations.Test;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestIgnore {@Testpublic void testa(){System.out.println("TestIgnore.testa");}@Test(enabled = true)public void testb(){System.out.println("TestIgnore.testb");}@Test(enabled = false)public void testc(){System.out.println("TestIgnore.testc");}
}
运行结果:
TestIgnore.testa
TestIgnore.testb
分组测试
场景︰只想执行个别或者某一部分的测试用例
package com.qzcsbj;import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestGroups {@Test(groups = "login")public void testa(){System.out.println("TestIgnore.testa");}@Test(groups = "submitOrder")public void testb(){System.out.println("TestIgnore.testb");}@Test(groups = "submitOrder")public void testc(){System.out.println("TestIgnore.testc");}@BeforeGroups("submitOrder")public void testBeforeGroups(){System.out.println("TestGroups.testBeforeGroups");}@AfterGroups("submitOrder")public void testAfterGroup(){System.out.println("TestGroups.testAfterGroup");}
}
输出结果:
TestIgnore.testa
TestGroups.testBeforeGroups
TestIgnore.testb
TestIgnore.testc
TestGroups.testAfterGroup
xml方式
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite"><!--<test verbose="2" preserve-order="true" name="test">--><test name="test"> <!--test必须有name属性--><groups><run><include name="submitOrder"/></run></groups><classes><class name="com.qzcsbj.TestGroups"/></classes></test>
</suite>
输出结果:
TestGroups.testBeforeGroups
TestIgnore.testb
TestIgnore.testc
TestGroups.testAfterGroup
依赖测试
字符串数组,默认是空
dependsOnMethods和BeforeMethod的区别是: BeforeMethod是每个方法前都要执行,而dependsOnMethods只是依赖的方法前执行
package com.qzcsbj;import org.testng.annotations.Test;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestDepend {@Test(dependsOnMethods = {"test2"})public void test(){System.out.println("TestAnnotation.test");}@Testpublic void test2(){System.out.println("TestAnnotation.test2");}
}
运行结果:
TestAnnotation.test2
TestAnnotation.test
如果被依赖方法执行失败,有依赖关系的方法不会被执行;
应用场景,登录失败,就不能进行下单等操作
package com.qzcsbj;import org.testng.annotations.Test;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestDepend {@Test(dependsOnMethods = {"test2"})public void test(){System.out.println("TestAnnotation.test");}@Testpublic void test2(){System.out.println("TestAnnotation.test2");throw new RuntimeException(); // 抛出一个异常}
}
运行结果:
TestAnnotation.test2java.lang.RuntimeExceptionat com.qzcsbj.TestDepend.test2(TestDepend.java:19)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)at org.testng.TestRunner.privateRun(TestRunner.java:648)at org.testng.TestRunner.run(TestRunner.java:505)at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)at org.testng.SuiteRunner.run(SuiteRunner.java:364)at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)at org.testng.TestNG.runSuites(TestNG.java:1049)at org.testng.TestNG.run(TestNG.java:1017)at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
超时
timeout属性的单位为毫秒。
package com.qzcsbj;import org.testng.annotations.Test;
/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestTimeOut {@Test(timeOut = 1000) // 单位为毫秒值,期望在1秒内得到结果public void test() throws InterruptedException {System.out.println("TestTimeOut.test");Thread.sleep(500);}@Test(timeOut = 1000)public void test2() throws InterruptedException {System.out.println("TestTimeOut.test2");for (int i = 10; i > 0; i--) {Thread.sleep(101);System.out.println(i);}System.out.println("执行结束。");}
}
输出结果:
TestTimeOut.test2
10
9
8
7
6
5
4
3
2org.testng.internal.thread.ThreadTimeoutException: Method com.qzcsbj.TestTimeOut.test2() didn't finish within the time-out 1000at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1953)at java.util.concurrent.ThreadPoolExecutor.tryTerminate(ThreadPoolExecutor.java:716)at java.util.concurrent.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:1014)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
断言
package com.qzcsbj;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class Add {public int sum(int a, int b){return a+b;}
}
package com.qzcsbj;import org.testng.Assert;
import org.testng.annotations.Test;public class MyTest {@Testpublic void test(){Add add = new Add();int actual = add.sum(1, 2);int expect = 2;Assert.assertEquals(actual,expect);}
}
参数化(数据驱动测试)
两种方式向测试方法传递参数:
利用testng.xml定义parameter
利用DataProviders
xml文件参数化
package com.qzcsbj;import org.testng.annotations.Parameters;
import org.testng.annotations.Test;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestParameter {@Test@Parameters({"name","id"})public void test(String name, int id){System.out.println("name=" + name + ", id=" + id);}
}
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite"><!--<test verbose="2" preserve-order="true" name="test">--><test name="test"> <!--test必须有name属性--><classes><class name="com.qzcsbj.TestParameter"><parameter name="name" value="qzcsbj"/><parameter name="id" value="1"/></class></classes></test>
</suite>
运行结果:
name=qzcsbj, id=1
DataProvider参数化
package com.qzcsbj;import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;/*** @博客 : www.cnblogs.com/uncleyong* @微信 : ren168632201* @描述 : <...>*/
public class TestDataProvider {@Test(dataProvider="data") // 和下面的name对应起来public void testDataProvider(String name, int id){System.out.println("name=" + name + ", id=" + id);}@DataProvider(name = "data") // 如果没有指定name,上面就写下面的方法名:providerDatapublic Object[][] providerData(){Object[][] datas = new Object[][]{{"zhangsan",1001},{"lisi",1002},{"wangwu",1003}};return datas;}
}
运行结果:
name=zhangsan, id=1001
name=lisi, id=1002
name=wangwu, id=1003
进一步优化,读取excel文件,写一个CaseUtil工具类,根据接口编号来获取这个接口的测试数据,并获取指定列,比如:
Object[][] datas = CaseUtil.getDataByApiId("1",columns);