遇一山,过一山,处处有风景;只要勇敢向前,一路尽是繁花盛开。 | (点击查看→)【测试干货】python/java自动化、持续集成、性能、测开、简历、笔试面试等

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>

 

常用注解

@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 {
    @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文件

在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 {
    @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

 

【bak】

原文:https://www.cnblogs.com/uncleyong/p/15867747.html

 

下一系列:自动化测试框架开发(java + testng + httpclient + allure)

 

posted @ 2022-02-07 18:08  全栈测试笔记  阅读(16888)  评论(2编辑  收藏  举报
浏览器标题切换
浏览器标题切换end