TestNG

简介

TestNG是一个受JUnit和NUnit启发的测试框架 ,有完善的用例管理模块,配合Maven能够很方便管理依赖第三方插件。使用TestNG可以做功能、接口、单元、集成的自动化测试。


1. 注解

2. 参数化测试

3. 支持依赖测试方法

4. 支持组概念

5. 支持多线程测试

6. 灵活的配置

对比Junit

  • 比Junit涵盖功能更全面

  • Junit更适合隔离性比较强的单元测试

  • TestNG更适合复杂的集成测试

使用步骤

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

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

  • 运行TestNG

使用

依赖

<dependencies>

    <dependency>

        <groupId>org.testng</groupId>

        <artifactId>testng</artifactId>

        <version>6.10</version>

    </dependency>

</dependencies>

注解
@Test

@Test

public void test01(){

    System.out.println("测试用例01");

}

运行结果:


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

测试用例01

===============================================

Default Suite

Total tests run: 1, Failures: 0, Skips: 0

===============================================

@BeforeMethod和@AfterMethod

每一个方法执行前执行BeforeMethod,每一个方法执行后执行AfterMethod


@AfterMethod

public void afterMethod(){

    System.out.println("AfterMethod");

}

@BeforeMethod

public void beforeMethod(){

    System.out.println("BeforeMethod");

}

@Test

public void test01(){

    System.out.println("测试用例01");

}

@Test

public void test02(){

    System.out.println("测试用例02");

}

运行结果:


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

BeforeMethod

测试用例01

AfterMethod

BeforeMethod

测试用例02

AfterMethod

===============================================

Default Suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

@BeforeClass和@AfterClass

测试类运行前执行BeforeClass,测试类运行后执行AfterClass

@BeforeMethod,@AfterMethod,@BeforeClass,@BeforeClass运行顺序如下


@AfterMethod

public void afterMethod(){

    System.out.println("AfterMethod");

}

@BeforeMethod

public void beforeMethod(){

    System.out.println("BeforeMethod");

}

@BeforeClass

public void beforeClass(){

    System.out.println("BeforeClass");

}

@AfterClass

public void afterClass(){

    System.out.println("AfterClass");

}

@Test

public void test01(){

    System.out.println("测试用例01");

}

@Test

public void test02(){

    System.out.println("测试用例02");

}

运行结果


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

BeforeClass

BeforeMethod

测试用例01

AfterMethod

BeforeMethod

测试用例02

AfterMethod

AfterClass

===============================================

Default Suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

@BeforeSuite和@AfterSuite

Suite可以包含多个类,在多个类运行之前执行BeforeSuite,多个类运行之后执行AfterSuite

套件测试

xml命名不限


package cn.fjx;

import org.testng.annotations.Test;

public class LoginTest {

    @Test

    public void login(){

        System.out.println("登陆成功");

    }

}


package cn.fjx;

import org.testng.annotations.Test;

public class SendMessageTest {

    @Test

    public void sendMessage(){

        System.out.println("发送消息");

    }

}


package cn.fjx;

import org.testng.annotations.*;

public class DemoTest {

    @AfterMethod

    public void afterMethod(){

        System.out.println("AfterMethod");

    }

    @BeforeMethod

    public void beforeMethod(){

        System.out.println("BeforeMethod");

    }

    @BeforeClass

    public void beforeClass(){

        System.out.println("BeforeClass");

    }

    @AfterClass

    public void afterClass(){

        System.out.println("AfterClass");

    }

    @BeforeSuite

    public void beforeSuit(){

        System.out.println("BeforeSuite套件");

    }

    @AfterSuite

    public void afterSuite(){

        System.out.println("AfterSuite套件");

    }

    @Test

    public void test01(){

        System.out.println("测试用例01");

    }

    @Test

    public void test02(){

        System.out.println("测试用例02");

    }

}


<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="test">

    <test name="login">

        <classes>

            <class name="cn.fjx.DemoTest"></class>

            <class name="cn.fjx.LoginTest"></class>

        </classes>

    </test>

    <test name="sendMessage">

        <classes>

            <class name="cn.fjx.DemoTest"></class>

            <class name="cn.fjx.SendMessageTest"></class>

        </classes>

    </test>

</suite>

运行testng.xml可以得到结果


[TestNG] Running:

  D:\xh-code\TestDemo\src\main\resources\testng.xml

BeforeSuite套件

BeforeClass

BeforeMethod

测试用例01

AfterMethod

BeforeMethod

测试用例02

AfterMethod

AfterClass

登陆成功

BeforeClass

BeforeMethod

测试用例01

AfterMethod

BeforeMethod

测试用例02

AfterMethod

AfterClass

发送消息

AfterSuite套件

===============================================

test

Total tests run: 6, Failures: 0, Skips: 0

===============================================

忽略测试

忽略测试是指本次测试执行中不想要执行的测试方法


@Test(enabled = false)


@Test(enabled = false)

public void test01(){

    System.out.println("测试用例01");

}

执行结果:


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

BeforeSuite套件

AfterSuite套件

===============================================

Default Suite

Total tests run: 0, Failures: 0, Skips: 0

===============================================

忽略测试时,Suite也会执行

@BeforeGroups和@AfterGroups

方法分组测试

BeforeGroups会在该组测试方法执行之前执行,AfterGroups会在该组测试方法执行之后执行


@BeforeGroups("apple")

public void appleBefore(){

    System.out.println("appleBefore");

}

@AfterGroups("apple")

public void appleAfter(){

    System.out.println("appleAfter");

}

@Test(groups = "apple")

public void apple1(){

    System.out.println("apple1");

}

@Test(groups = "apple")

public void apple2(){

    System.out.println("apple2");

}

@Test(groups = "pear1")

public void pear1(){

    System.out.println("pear1");

}

@Test(groups = "pear2")

public void pear2(){

    System.out.println("pear2");

}

运行结果:


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

appleBefore

apple1

apple2

appleAfter

pear1

pear2

===============================================

Default Suite

Total tests run: 4, Failures: 0, Skips: 0

===============================================

类分组测试

可以选择组或者排除组进行测试,一组可以包含多个类

xml命名不限


package cn.fjx.group;

import org.testng.annotations.Test;

@Test(groups = "apple")

public class GroupOnClass01 {

    public void apple01(){

        System.out.println("apple01");

    }

    public void apple02(){

        System.out.println("apple02");

    }

}


package cn.fjx.group;

import org.testng.annotations.Test;

@Test(groups = "apple")

public class GroupOnClass02 {

    public void apple01(){

        System.out.println("apple01");

    }

    public void apple02(){

        System.out.println("apple02");

    }

}


package cn.fjx.group;

import org.testng.annotations.Test;

@Test(groups = "pear")

public class GroupOnClass03 {

    public void pear01(){

        System.out.println("pear01");

    }

    public void pear02(){

        System.out.println("pear02");

    }

}


<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="test">

    <test name="runApple">

        <groups>

            <run>

                <include name="apple"/>

            </run>

        </groups>

        <classes>

            <class name="cn.fjx.group.GroupOnClass01"></class>

            <class name="cn.fjx.group.GroupOnClass02"></class>

            <class name="cn.fjx.group.GroupOnClass03"></class>

        </classes>

    </test>

</suite>

运行结果:


[TestNG] Running:

  D:\xh-code\TestDemo\src\main\resources\GroupsOnClass.xml

apple01

apple02

apple01

apple02

===============================================

test

Total tests run: 4, Failures: 0, Skips: 0

===============================================

异常测试

必须在方法中抛出异常,否则会报错


@Test(expectedExceptions = RuntimeException.class)

public void exception01(){

    System.out.println("运行时异常01");

}

@Test(expectedExceptions = RuntimeException.class)

public void exception02(){

    System.out.println("运行时异常02");

    throw new RuntimeException();

}

运行结果


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

运行时异常01

org.testng.TestException:

Method ExceptionTest.exception01()[pri:0, instance:cn.fjx.exception.ExceptionTest@768debd] should have thrown an exception of type class java.lang.RuntimeException ...

运行时异常02

===============================================

Default Suite

Total tests run: 2, Failures: 1, Skips: 0

===============================================

依赖测试

某个方法执行时,必须先执行另外多个方法,这时可以使用dependsOnMethods


@Test

public void test01(){

    System.out.println("test01");

}

@Test(dependsOnMethods = "test01")

public void test02(){

    System.out.println("test02");

}


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

test01

test02

===============================================

Default Suite

Total tests run: 2, Failures: 0, Skips: 0

===============================================

当第一个方法出现异常时,第二个方法不会执行


@Test

public void test01(){

    System.out.println("test01");

    throw new RuntimeException();

}

@Test(dependsOnMethods = "test01")

public void test02(){

    System.out.println("test02");

}


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

test01

java.lang.RuntimeException...

Test ignored.

===============================================

Default Suite

Total tests run: 2, Failures: 1, Skips: 1

===============================================

参数化测试

TestNG允许在TestMethod以及@Before/After类注解、@Factory类注解的方法中传入参数。 参数传递的方式有两种,一种是借助xml文件配置,另一种是以编码的方式传递参数。

  1. xml方式传递参数

xml命名不限


<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="test">

    <test name="param">

        <classes>

            <class name="cn.fjx.parameter.ParameterTest"/>

            <parameter name="name" value="fjx"/>

            <parameter name="age" value="20"/>

        </classes>

    </test>

</suite>


package cn.fjx.parameter;

import org.testng.annotations.Parameters;

import org.testng.annotations.Test;

public class ParameterTest {

    @Test

    @Parameters({"name","age"})

    public void test01(String name, Integer age){

        System.out.println("name:"+name +" age:"+ age);

    }

}

运行结果


[TestNG] Running:

  D:\xh-code\TestDemo\src\main\resources\parameters.xml

name:fjx age:20

===============================================

test

Total tests run: 1, Failures: 0, Skips: 0

===============================================

  1. 编码的方式传递参数

为测试用例提供参数,有多少组参数就会执行多少次用例,因此它是一个让测试类实例的某个方法执行多次,但每次执行都使用同一个实例。


@Test(dataProvider = "data")

public void test02(String name, Integer age){

    System.out.println("name:"+name +" age:"+ age);

}

@DataProvider(name = "data")

public Object[][] testData(){

    return new Object[][]{

        {"fjx01",123},

        {"fjx02",456},

        {"fjx03",789}

    };

}

运行结果:运行test02会循环得到testData中的数据


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

name:fjx01 age:123

name:fjx02 age:456

name:fjx03 age:789

===============================================

Default Suite

Total tests run: 3, Failures: 0, Skips: 0

===============================================

  1. @Factory

创建一个测试类的多个实例,每个实例中的所有测试用例都会被执行,因此它是一个测试类被执行多次,每次执行采用的是不同实例。


package cn.fjx.factory;

import org.testng.annotations.Factory;

public class SimpleTestFactory {



    @Factory

    public Object[] factoryMethod(){

        return new Object[] { new SimpleTest(0), new SimpleTest(10)};

    }

}


package cn.fjx.factory;

import org.testng.annotations.Test;

public class SimpleTest {

    private int para;

    public SimpleTest(int para) {

        this.para = para;

    }



    @Test

    public void testMethodOne(){

        int value = para + 1;

        System.out.println("Test method one output: " + value);

    }

    @Test

    public void testMethodTwo(){

        int value = para + 2;

        System.out.println("Test method two output: " + value);

    }

}

执行SimpleTestFactory得到运行结果:


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

Test method one output: 11

Test method one output: 1

Test method two output: 12

Test method two output: 2

===============================================

Default Suite

Total tests run: 4, Failures: 0, Skips: 0

===============================================

超时测试

@Test(timeOut = 1000)

public void test01() throws InterruptedException {

    Thread.sleep(2000);

}

运行结果:


[TestNG] Running:

  C:\Users\Administrator\.IntelliJIdea2018.1\system\temp-testng-customsuite.xml

org.testng.internal.thread.ThreadTimeoutException: Method cn.fjx.timeout.TimeOutTest.test01() didn't finish within the time-out 1000...

===============================================

Default Suite

Total tests run: 1, Failures: 1, Skips: 0

===============================================

testng.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<!--

suite有以下属性:

    name:suite名称,测试报告中展现

    verbose: 在控制台中如何输出,该设置不影响测试报告,可以设置0-10,越大输出越详细

    allow-return-values:如果设置为false,被@Test注解且有return的方法被忽略执行

    annotations:如果为"javadoc", 则使用javadoc注解,否则使用jdk注解

    configfailurepolicy:字典:continue,skip,如果@Before*方法失败,TestNG是否应该继续执行套件中的其余测试,默认为skip

    data-provider-thread-count:并发执行data-provider的线程数,默认大小为10

    group-by-instances:默认情况下,依赖方法按类分组。例如,如果方法b()依赖于方法a(),并且您有几个包含这些方法的类实例(因为数据提供者的工厂),

    那么调用顺序将为:signIn("us"),signIn("uk"),signOut("us"),signOut("uk")。group-by-instances设置为true的话,调用顺序将为:signIn("us"),signOut("us"),signIn("uk"),signOut("uk")

    guice-stage:创建父注入器的stage

    junit:是否以junit模式运行

    object-factory:用于实现IObjectFactory的类,实例化测试对象

    parallel:是否多线程并发运行测试,默认为false,字典:classes,methods,instances,tests,true,false

    parent-module:用于创建所有guice注入器的父注入器的模块

    preserve-order:默认情况下,TestNG将按照在XML文件配置的顺序运行测试。如果希望以不可预知的顺序运行文件中列出的类和方法,可将preserve-order属性设置为false

    skipfailedinvocationcounts:是否跳过失败的调用

    thread-count:使用并行模式,要使用的线程池的大小。

    time-out:为具体执行单元设定一个超时时间,方法(parallel="methods")或测试(parallel="tests")

-->

<suite name="Suite" verbose="1">

    <!--一个suite可以包含多个test,test有以下属性:

    name:这个测试的名称(将出现在报告中)

    annotations:同suite套件属性

    allow-return-values:同suite套件属性

    verbose:同suite套件属性

    enabled:启用/禁用当前测试的标志。默认值:true

    group-by-instances:同suite套件属性

    junit:同suite套件属性

    parallel:同suite套件属性

    preserve-order:同suite套件属性

    skipfailedinvocationcounts:同suite套件属性

    thread-count:同suite套件属性

    time-out:同suite套件属性

    -->

    <test name="test">

        <!--指定执行包-->

        <packages>

            <!--包名称-->

            <package name="com">

            </package>

        </packages>

    </test>

    <!--testng.xml中只能设置一个<suite>标签,可通过<suite-files >标签实现多个测试集设置。-->

    <suite-files>

        <suite-file path="testNG.xml"/>

        <suite-file path="testNG.xml"/>

    </suite-files>

    <!--设置监听器-->

    <listeners>

        <listener class-name="TestNGHelloWorld1"/>

    </listeners>

    <!--方法拦截器-->

    <method-selectors>

        <method-selector>

            <selector-class name="TestNGHelloWorld1"/>

        </method-selector>

    </method-selectors>

    <!--方法拦截器-->

    <method-selectors>

        <method-selector>

            <script language="java"/>

        </method-selector>

    </method-selectors>

    <test name="TestNG1">

        <groups>

            <!--组中组,即test4包含了test1和test3两个组-->

            <define name="test4">

                <include name="test1"/>

                <include name="test3"/>

            </define>

            <!--运行test4组,不运行test2组-->

            <run>

                <include name="test4"/>

                <exclude name="test2"/>

            </run>

            <!--test3组依赖于test1,test2组,多个依赖用空格隔开-->

            <dependencies>

                <group name="test3" depends-on="test1 test2"/>

            </dependencies>

        </groups>

        <!--类-->

        <classes>

            <class name="TestNGHelloWorld1"/>

        </classes>

    </test> <!-- TestNG -->

    <test name="TestNG2">

        <!--入参,分别为参数名和参数值-->

        <parameter name="str" value="Test1"/>

        <classes>

            <class name="TestNGHelloWorld1">

                <!--类中的方法-->

                <methods>

                    <!--执行该方法-->

                    <include name="helloWorldTest1"/>

                    <!--不执行该方法-->

                    <exclude name="helloWorldTest2"/>

                </methods>

            </class>

        </classes>

    </test>

</suite>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容

  • 在自动化测试时,经常会用到TestNg 或 Junit 测试框架。那么它们之间有什么联系和区别,如何使用呢?在面试...
    乘风破浪的姐姐阅读 1,683评论 0 0
  • JUnit 4和TestNG都是Java中非常受欢迎的单元测试框架。两种框架在功能上看起来非常相似。 哪一个更好?...
    易百教程阅读 4,993评论 2 6
  • TestNG是Java中的一个测试框架, 类似于JUnit 和NUnit, 功能都差不多, 只是功能更加强大,使...
    hurtsogood阅读 1,244评论 0 2
  • 作业七:记录一个你印象深刻的梦境。 此刻我正坐在地铁里,非常疲劳,眼睛干涩,有点头晕,我特别想把身体躺着,让后背能...
    西域小达阅读 178评论 0 2
  • 奔走于草原上的甜美歌喉 回荡在山野间的稚雅童声 朝霞是高音 晚霞是低音 从黎明唱到黄昏 唱出草原与牧人的深情 春风...
    山上人家123阅读 314评论 5 12