侧边栏壁纸
博主头像
一朵云的博客博主等级

拥抱生活,向阳而生。

  • 累计撰写 67 篇文章
  • 累计创建 25 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

TestNG -- 介绍与使用

一朵云
2021-03-15 / 0 评论 / 2 点赞 / 7645 阅读 / 15395 字

介绍

  TestNG是一个设计用来简化广泛的测试需求的测试框架,从单元测试(隔离测试一个类)到集成测试(测试由有多个类多个包甚至多个外部框架组成的整个系统,例如运用服务器)。

  编写一个测试的过程有三个典型步骤:

  ①、编写测试的 业务逻辑并在代码中插入TestNG annotation

  ②、将测试信息添加到testng.xml文件或者build.xml中

  ③、运行TestNG

对比

  ①、TestNg更适合复杂的继承测试,Junit更适合隔离性比较强的单元测试。

  ②、比junit涵盖功能更全面,Testng可以通过注解去区分执行方法的先后和依赖关系,而junit做不到。

  ③、TestNg因为有xml文件,所以TestNg可以针对一组测试类共同测试,而junit只能一个类资源内部测试,相对比较耗时。

  ④、测试套件运行失败,JUnit 4会重新运行整个测试套件。TestNG运行失败时,会创建一个XML文件说明失败的测试,利用这个文件执行程序,就不会重复运行已经成功的测试。

参考:https://mkyong.com/unittest/junit-4-vs-testng-comparison/

准备

maven项目直接引入依赖:

<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
	<groupId>org.testng</groupId>
	<artifactId>testng</artifactId>
	<version>7.6.0</version>
	<scope>test</scope>
</dependency>

使用

TestNG基本注解

注解作用
@Test标记一个类或方法作为测试的一部分
@BeforeMethod在每个@Test方法前都会运行
@AfterMethod在每个@Test方法后都会运行
@BeforeClass该方法在类运行前运行,且仅运行一次
@AfterClass该方法在类运行后运行,且仅运行一次
@BeforSuite测试套件,类运行前运行(@BeforeClass之前),可通过xml包裹多个测试类
@AfterSuite测试套件,类运行后运行(@AfterClass之后),可通过xml包裹多个测试类

执行顺序演示

import org.testng.annotations.*;
 
public class TestNGDemo {

    @Test
    public void test1() {
        System.out.println("test1()执行了!");
    }

    @Test
    public void test2() {
        System.out.println("test2()执行了!");
    }

    @BeforeMethod
    public void test3() {
        System.out.println("BeforeMethod的test3()执行了!");
    }

    @AfterMethod
    public void test4() {
        System.out.println("AfterMethod的test4()执行了!");
    }

    @BeforeClass
    public void test5() {
        System.out.println("BeforeClass的test5()执行了!");
    }

    @AfterClass
    public void test6() {
        System.out.println("AfterClass的test6()执行了!");
    }

    @BeforeSuite
    public void test7() {
        System.out.println("BeforeSuite的test7()执行了!");
    }

    @AfterSuite
    public void test8() {
        System.out.println("AfterSuite的test8()执行了!");
    }
}

执行结果

BeforeSuite的test7()执行了!

BeforeClass的test5()执行了!

BeforeMethod的test3()执行了!

test1()执行了!

AfterMethod的test4()执行了!

BeforeMethod的test3()执行了!

test2()执行了!

AfterMethod的test4()执行了!

AfterClass的test6()执行了!

AfterSuite的test8()执行了!

测试套件

  在前面的代码基础上,我们想只执行TestNGDemo类的test1()方法,可以在resources资源目录下新建个xml文件,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="mySuite">
    <test name="myName">
        <classes>
            <class name="com.dc.TestNGDemo">
                <methods>
                    <!-- 仅包含TestNGDemo类中的test1()方法 -->
                    <include name="test1"></include>
                    <!-- 排除TestNGDemo类中的test2()方法 -->
                    <!--<exclude name="test2"></exclude>-->
                </methods>
            </class>
        </classes>
    </test>
</suite>

忽略测试

  当我们不想要某个方法或类参与测试时,又不想动xml,我们可以为@Test注解加个属性值enabled=false,表示不参与测试。

import org.testng.annotations.*;

public class TestNGDemo {

    @Test(enabled = false)
    public void test1() {
        System.out.println("test1()执行了!");
    }
}

分组测试

基于方法的分组

import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;

public class TestNGGroupDemo {

    @Test(groups = "G1")
    public void test1() {
        System.out.println("G1的test1()执行了!");
    }

    @Test(groups = "G2")
    public void test2() {
        System.out.println("G2的test2()执行了!");
    }

    @Test(groups = "G1")
    public void test3() {
        System.out.println("G1的test3()执行了!");
    }

    @BeforeGroups("G1")
    public void test4() {
        System.out.println("G1分组的BeforeGroups的test4()执行了!");
    }

    @AfterGroups("G1")
    public void test5() {
        System.out.println("G1分组的AfterGroups的test5()执行了!");
    }

    @BeforeGroups("G2")
    public void test6() {
        System.out.println("G2分组的BeforeGroups的test6()执行了!");
    }

    @AfterGroups("G2")
    public void test7() {
        System.out.println("G2分组的AfterGroups的test7()执行了!");
    }

}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="mySuite2">
    <test name="myName2">
        <groups>
            <run>
                <include name="G1"></include>
            </run>
        </groups>
        
        <classes>
            <class name="com.dc.TestNGGroupDemo" />
        </classes>
    </test>
</suite>

执行结果

G1分组的BeforeGroups的test4()执行了!

G1的test1()执行了!

G1的test3()执行了!

G1分组的AfterGroups的test5()执行了!

基于类的分组

import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;

@Test(groups = "CT1")
public class TestNGGroupDemo {

    @Test(groups = "G1")
    public void test1() {
        System.out.println("G1的test1()执行了!");
    }

    @Test(groups = "G2")
    public void test2() {
        System.out.println("G2的test2()执行了!");
    }

    @Test(groups = "G1")
    public void test3() {
        System.out.println("G1的test3()执行了!");
    }

    @BeforeGroups("G1")
    public void test4() {
        System.out.println("G1分组的BeforeGroups的test4()执行了!");
    }

    @AfterGroups("G1")
    public void test5() {
        System.out.println("G1分组的AfterGroups的test5()执行了!");
    }

    @BeforeGroups("G2")
    public void test6() {
        System.out.println("G2分组的BeforeGroups的test6()执行了!");
    }

    @AfterGroups("G2")
    public void test7() {
        System.out.println("G2分组的AfterGroups的test7()执行了!");
    }

}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="mySuite2">
    <test name="myName2">
        <groups>
            <run>
                <include name="CT1"></include>
            </run>
        </groups>
        
        <classes>
            <class name="com.dc.TestNGGroupDemo" />
        </classes>
    </test>
</suite>

执行结果

G1分组的BeforeGroups的test4()执行了!

G1的test1()执行了!

G2分组的BeforeGroups的test6()执行了!

G2的test2()执行了!

G2分组的AfterGroups的test7()执行了!

G1的test3()执行了!

G1分组的AfterGroups的test5()执行了!

异常测试:

@Test(expectedExceptions = XXException.class)

  当我们想要验证测试方法是否会出现预期异常,我们可以为@Test注解添加属性expectedExceptions,当属性值与实际异常相同时,会忽略,执行通过。反之没有出现指定异常时,TestNG会提示TestException。

  • 未添加注解属性时:
    image.png

  • 添加了注解属性,且异常类匹配:
    image.png

  • 添加了注解属性,但异常类不匹配:
    image.png

依赖测试:

@Test(dependsOnMethods = {“使用了@Test的别的方法名”})

  可通过该注解进行方法的顺序关联,依赖关联。

例1:
  通过dependsOnMethods依赖,将原本test1>test2>test3的顺序改为了test1>test3>test2。

import org.testng.annotations.Test;

public class TestNRelyDemo {

    @Test
    public void test1(){
        System.out.println("test1()执行了!");
    }

    @Test(dependsOnMethods = "test3")
    public void test2(){
        System.out.println("test2()执行了!");
    }

    @Test(dependsOnMethods = "test1")
    public void test3(){
        System.out.println("test3()执行了!");
    }
    
}

执行结果

test1()执行了!

test3()执行了!

test2()执行了!

例2:
  当被依赖的方法test1()执行失败,那么test2()、test3()都不会执行。

import org.testng.annotations.Test;

public class TestNRelyDemo {

    @Test
    public void test1(){
        System.out.println("test1()执行了!");
        throw new NullPointerException();
    }

    @Test(dependsOnMethods = "test3")
    public void test2(){
        System.out.println("test2()执行了!");
    }

    @Test(dependsOnMethods = "test1")
    public void test3(){
        System.out.println("test3()执行了!");
    }

}

执行结果:
  test1报错,后面依赖test1的方法直接忽略不执行。
image.png

参数化测试

@Parameters({“param1”,”param2”,......})

xml传参

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class TestNGParamDemo {

    @Test
    @Parameters({"name","age"})
    public void test1(String name,int age){
        System.out.println("name="+name+"   age="+age);
    }
    
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="mySuite3">
    <test name="myTest3">
        <classes>
            <class name="com.dc.TestNGParamDemo">
                <methods>
                    <include name="test1">
                        <parameter name="name" value="张三"></parameter>
                        <parameter name="age" value="18"></parameter>
                    </include>
                </methods>
            </class>
        </classes>
    </test>
</suite>

执行结果:
image.png

对象传参

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestNGParamDemo {
    
    @Test(dataProvider = "user")
    public void test1(String name,int age){
        System.out.println("name="+name+"   age="+age);
    }

    @DataProvider(name="user")
    public Object[][] providerData(){
        Object[][] user = new Object[][]{
                {"张三",19},
                {"李四",24},
                {"王五",30}
        };
        return user;
    }
}

执行结果:
image.png

方法映射传参

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.lang.reflect.Method;

public class TestNGParamDemo {

    @Test(dataProvider = "methodData")
    public void test2(String name,int age){
        System.out.println("name="+name+"   age="+age);
    }

    @Test(dataProvider = "methodData")
    public void test3(String name,int age){
        System.out.println("name="+name+"   age="+age);
    }

    @DataProvider(name="methodData")
    public Object[][] providerMethodData(Method method){
        Object[][] result = null;

        if (method.getName().equals("test2")){
            result = new Object[][]{
                    {"张三", 19}
            };
        }else if (method.getName().equals("test3")){
            result = new Object[][]{
                    {"李四",24}
            };
        }else {
            result = new Object[][]{
                    {"王五",34}
            };
        }
        return result;
    }

}

执行结果:
image.png

超时测试

@Test(timeOut = 毫秒)
超过时间就报错

image.png

多线程测试

截图.png

2

评论区