TestNG的使用结合Allure测试结果展示
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>
常用注解
@BeforeSuite / @AfterSuite
@BeforeTest / @AfterTest
@BeforeClass / @AfterClass,在类运行之前/后运行
@BeforeMethod / @AfterMethod,在测试方法之前/后运行
分组测试
场景︰只想执行个别或者某一部分的测试用例
package com.qzcsbj;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
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;
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;
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)
超时
timeout属性的单位为毫秒。
package com.qzcsbj;
import org.testng.annotations.Test;
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
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;
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;
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="hyqtest"/>
<parameter name="id" value="1"/>
</class>
</classes>
</test>
</suite>
结果:
name=hyqtest, id=12
DataProvider参数化
代码和数据未分离
package com.qzcsbj;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
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中
LoginCase.java
用课程中的数据类型封装
package com.qzcsbj;
import com.qzcsbj.HttpPostRequest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.HashMap;
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
结合Allure结果展示
先导入坐标:
<build>
<finalName>apiTest</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<!-- copy excel文件 -->
<resource>
<directory>${basedir}/data</directory>
<targetPath>${basedir}/target/data/</targetPath>
<includes>
<include>*.xlsx</include>
<include>*.csv</include>
<include>*.txt</include>
<include>*.json</include>
</includes>
</resource>
</resources>
<plugins>
<!-- 依赖包处理 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<!-- 默认配置 compile 所有编译运行的包 除了test -->
<includeScope>compile</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<!-- maven jar插件扩展 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<!-- lib依赖 包和main方法关系通过 MANIFEST.MF配置文件维护 -->
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>ApiTest</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<!--设置参数命令行-->
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
<!-- 集成testng xml -->
<suiteXmlFiles>
<suiteXmlFile>src\main\resources\testng.xml</suiteXmlFile>
</suiteXmlFiles>
<workingDirectory>target/</workingDirectory>
<systemProperties>
<property>
<!-- 配置 allure 结果存储路径 -->
<name>allure.results.directory</name>
<value>${basedir}/target/allure-results</value>
</property>
</systemProperties>
<!-- 是否跳过单元测试 -->
<skipTests>false</skipTests>
<!-- 单元测试出错是否继续 -->
<testFailureIgnore>true</testFailureIgnore>
<!-- 中文问题 -->
<argLine>
-Dfile.encoding=UTF-8
</argLine>
</configuration>
</plugin>
</plugins>
</build>
编写目标测试类及testng.xml
右键先run一下testng.xml文件
双击右侧的maven中的test进行构建测试,此时在工程中生成target目录并生成allure结果文件
点击maven图标 输入命令 mvn io.qameta.allure:allure-maven:serve
即可自动弹出allure结果弹窗
本文来自博客园,作者:Joson6350,转载请注明原文链接:https://www.cnblogs.com/josonhuang/p/17055421.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?