java自动化前置基础(下):TestNG用法
java自动化前置基础(上):fastjson、jsonpath、httpclient等
TestNG详解(01):xml文件创建、详解
TestNG详解(02):xml文件使用
TestNG详解(03):常用注解
TestNG详解(04):参数化 - xml文件
TestNG详解(05):参数化 - @DataProvider
TestNG详解(06):忽略测试
TestNG详解(07):分组测试
TestNG详解(08):依赖测试
TestNG详解(09):超时
TestNG详解(10):断言
TestNG详解(11):并行执行
TestNG详解(12):重试
TestNG详解(13):踩坑汇总
TestNG简介
Testng是一套开源测试框架,是从Junit继承而来,testng意为test next generation
创建maven项目,添加依赖
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
常用注解
package com.qzcsbj;
import org.testng.annotations.*;
import org.testng.annotations.Test;
/**
* @描述 : <...>
* @博客 : www.cnblogs.com/uncleyong
* @微信 : ren168632201
*/
public class TestAnnotation {
@Test
public void test(){
System.out.println("TestAnnotation.test");
System.out.println("线程ID:" + Thread.currentThread().getId());
}
@Test
public void test2(){
System.out.println("TestAnnotation.test2");
}
@BeforeMethod
public void beforeMethodTest(){
System.out.println("TestAnnotation.beforeMethodTest");
}
@AfterMethod
public void afterMethodTest(){
System.out.println("TestAnnotation.afterMethodTest");
}
@BeforeClass
public void beforeClassTest(){
System.out.println("TestAnnotation.beforeClassTest");
}
@AfterClass
public void afterClassTest(){
System.out.println("TestAnnotation.afterClassTest");
}
@BeforeSuite
public void beforeSuiteTest(){
System.out.println("TestAnnotation.beforeSuiteTest");
}
@AfterSuite
public 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文件
<?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 {
@Test
public void test(){
System.out.println("TestAnnotation.test");
System.out.println("线程ID:" + Thread.currentThread().getId());
}
@Test
public void test2(){
System.out.println("TestAnnotation.test2");
}
@BeforeMethod
public void beforeMethodTest(){
System.out.println("TestAnnotation.beforeMethodTest");
}
@AfterMethod
public void afterMethodTest(){
System.out.println("TestAnnotation.afterMethodTest");
}
@BeforeClass
public void beforeClassTest(){
System.out.println("TestAnnotation.beforeClassTest");
}
@AfterClass
public void afterClassTest(){
System.out.println("TestAnnotation.afterClassTest");
}
@BeforeSuite
public void beforeSuiteTest(){
System.out.println("TestAnnotation.beforeSuiteTest");
}
@AfterSuite
public 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 {
@Test
public void testb(){
System.out.println("TestAnnotation.testb==");
System.out.println("线程ID:" + Thread.currentThread().getId());
}
@Test
public void testb2(){
System.out.println("TestAnnotationB.testb2==");
}
@BeforeMethod
public void beforeMethodTestb(){
System.out.println("TestAnnotationB.beforeMethodTestb==");
}
@AfterMethod
public void afterMethodTestb(){
System.out.println("TestAnnotationB.afterMethodTestb==");
}
@BeforeClass
public void beforeClassTestb(){
System.out.println("TestAnnotationB.beforeClassTestb==");
}
@AfterClass
public void afterClassTestb(){
System.out.println("TestAnnotationB.afterClassTestb==");
}
@BeforeSuite
public void beforeSuiteTestb(){
System.out.println("TestAnnotationB.beforeSuiteTestb==");
}
@AfterSuite
public void afterSuiteTestb(){
System.out.println("TestAnnotationB.afterSuiteTestb==");
}
}
输出结果:
TestAnnotation.beforeSuiteTest TestAnnotationB.beforeSuiteTestb== TestAnnotation.beforeClassTest TestAnnotation.beforeMethodTest TestAnnotation.test 线程ID:1 TestAnnotation.afterMethodTest TestAnnotation.beforeMethodTest TestAnnotation.test2 TestAnnotation.afterMethodTest TestAnnotation.afterClassTest TestAnnotationB.beforeClassTestb== TestAnnotationB.beforeMethodTestb== TestAnnotation.testb== 线程ID:1 TestAnnotationB.afterMethodTestb== TestAnnotationB.afterClassTestb== TestAnnotation.afterSuiteTest TestAnnotationB.afterSuiteTestb==
忽略测试
测试过程中,问题还没解决,可以先忽略,也就是不执行此方法
package com.qzcsbj;
import org.testng.annotations.Test;
/**
* @博客 : www.cnblogs.com/uncleyong
* @微信 : ren168632201
* @描述 : <...>
*/
public class TestIgnore {
@Test
public 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");
}
@Test
public 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");
}
@Test
public void test2(){
System.out.println("TestAnnotation.test2");
throw new RuntimeException(); // 抛出一个异常
}
}
运行结果:
TestAnnotation.test2 java.lang.RuntimeException at 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 2 org.testng.internal.thread.ThreadTimeoutException: Method com.qzcsbj.TestTimeOut.test2() didn't finish within the time-out 1000 at 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 {
@Test
public 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,上面就写下面的方法名:providerData
public 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中
sheet名为data

ExcelUtil.java
package com.qzcsbj;
import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* @公众号 : 全栈测试笔记
* @博客 : www.cnblogs.com/uncleyong
* @微信 : ren168632201
* @描述 : <>
*/
public class ExcelUtil {
// 方法也可以根据情况定义更多参数,比如读取excel的列范围
public static Object[][] getdataFromExcel(String excelPath){
Object[][] datas = null;
try {
// 获取workbook对象
Workbook workbook = WorkbookFactory.create(new File(excelPath));
// 获取sheet对象
Sheet sheet = workbook.getSheet("data");
datas = new Object[4][2];
// 获取行
for (int i = 1; i < 5; i++) {
Row row = sheet.getRow(i);
// 获取列
for (int j=0; j<=1;j++){
Cell cell = row.getCell(j);
cell.setCellType(CellType.STRING);
String value = cell.getStringCellValue();
datas[i-1][j] = value;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return datas;
}
public static void main(String[] args) {
String excelPath = "E:\\case.xlsx";
Object[][] datas = getdataFromExcel(excelPath);
for (Object[] data : datas) {
System.out.println(Arrays.toString(data));
}
}
}
上面读取到的数据

LoginCase.java
package com.qzcsbj;
import com.qzcsbj.HttpPostRequest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.HashMap;
/**
* @博客 : www.cnblogs.com/uncleyong
* @微信 : ren168632201
* @描述 : <...>
*/
public class LoginCase {
@Test(dataProvider = "datasFromExcel") // 多条数据,且数据和代码分离
public void test(String username, String password){
String url = "http://127.0.0.1:9999/login";
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username);
params.put("password", password);
String res = HttpPostRequest.postRequest(url, params);
System.out.println("入参:username=" + username + ", password=" + password);
System.out.println("响应:" + res);
System.out.println("============================\n");
}
@DataProvider(name = "datasFromExcel")
public Object[][] datasFromExcel(){
Object[][] datas = ExcelUtil.getdataFromExcel("E:\\case.xlsx");
return datas;
}
}

进一步优化
每行数据封装到对象或者map,返回:Iterator<Object[]>
每个一维里面是一个对象或者map
原文:https://www.cnblogs.com/uncleyong/p/15867747.html
下一系列:自动化测试框架开发(java + testng + httpclient + allure)
__EOF__
关于博主:擅长性能、全链路、自动化、企业级自动化持续集成(DevTestOps)、测开等
面试必备:项目实战(性能、自动化)、简历笔试,https://www.cnblogs.com/uncleyong/p/15777706.html
测试提升:从测试小白到高级测试修炼之路,https://www.cnblogs.com/uncleyong/p/10530261.html
欢迎分享:如果您觉得文章对您有帮助,欢迎转载、分享,也可以点击文章右下角【推荐】一下!

浙公网安备 33010602011771号