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结果弹窗
 
posted @ 2023-01-16 15:03  Joson6350  阅读(174)  评论(0编辑  收藏  举报
欢迎联系