TestNG

作者: 断点o | 来源:发表于2020-01-16 15:34 被阅读0次

    简介

    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>
    
    

    相关文章

      网友评论

          本文标题:TestNG

          本文链接:https://www.haomeiwen.com/subject/aaifzctx.html