TestNG系列-TestNG进阶

作者: zi萱 | 来源:发表于2019-07-25 20:45 被阅读21次
    猛戳:第一篇-TestNG入门

    时隔许久,不能再拖拉了。今天主要讲一下第二篇testng的一些特性。

    1.TestNG分组、依赖
    2.异常测试、忽略测试、超时测试
    3.多线程测试
    4.TestNG监听器
    其中,第1点和第4点是我们着重要理解消化的,2、3点提醒您TestNG有许多已知属性,用到的时候能想起来就行。

    一、TestNG分组、依赖

    1.分组

    • 假设现在有这样一个简单架构,支付是单独的底层服务,为券支付和会员卡支付服务提供基础功能,券支付包含券+现金支付类型和单独的券支付类型,会员卡支付包含会员卡+现金支付类型和单独会员卡支付。
    • 那么我现在有一些支付接口case,假如只修改了券支付逻辑,那么需要每次将支付case全部回归吗?假如只修改了现金支付逻辑,我该怎么有选择性的回归呢?


      image.png
    • 我们只需要将对应的case进行分组,就可以进行分组测试了。
    • 下面是如何去使用groups属性:可以指定一个方法/类属于多个组,再配置xml文件增加groups标签即可。
    public class GroupTest1 {
        @BeforeGroups("group2")
        public void beforeGroups() {
            System.out.println("testGroup1-beforeGroup");
        }
        @Test(groups = "group1")
        public void testGroup11() {
            System.out.println("testGroup11");
        }
    
        @Test(groups = {"group1", "group2"})
        public void testGroup12() {
            System.out.println("testGroup12");
        }
    }
    
    public class GroupTest2 {
        @org.testng.annotations.AfterGroups("group2")
        public void afterGroups() {
            System.out.println("testGroup2-afterGroup");
        }
        @org.testng.annotations.Test(groups = "group2")
        public void testGroup11() {
            System.out.println("testGroup21");
        }
    
        @org.testng.annotations.Test(groups = {"group1","group2"})
        public void testGroup12() {
            System.out.println("testGroup22");
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="TestGroupSuite">
        <test name="GroupTest">
            <groups>
                <run>
                    <include name="group1"/>
                    <include name="group2"/>
                </run>
            </groups>
            <classes>
                <class name="com.test.testng.Lesson5Groups.GroupTest1"/>
                <class name="com.test.testng.Lesson5Groups.GroupTest2"/>
            </classes>
        </test>
    </suite>
    

    2.依赖

    • 假设我们要测试一个买电影票的场景,我们先获取场次列表,再获取某个选中场次的座位图,再去下单,再去支付。


      image.png
    • 使用TestNG怎样能把他们很好的串起来呢?那么就用到了dependOnXX这个属性了,这里着重说一下dependOnMethod,当你需要做场景测试的时候,你可以写一个完整的场景类,从前到后让场景活灵活现起来。如果上一个步骤失败的话下面的步骤就skip了。
    public class DependTest {
        @Test
        public void getList() {
            System.out.println("getList");
        }
    
        @Test(dependsOnMethods = "getList")
        public void getSeatList() {
            System.out.println("getSeatList");
        }
    
        @Test(dependsOnMethods = "getSeatList")
        public void addOrder() {
            System.out.println("addOrder");
        }
    
        @Test(dependsOnMethods = "addOrder")
        public void pay() {
            System.out.println("pay");
        }
    
    }
    

    二、异常测试、忽略测试、超时测试

    1.异常测试

    如果你期望被测代码抛出一个异常,那么请加expectedExceptions属性

    public class ExceptionTest {
        //不抛出异常Test失败
        @Test(expectedExceptions = NumberFormatException.class)
        public void testException() {
            MathSolution.Add(1, 2);
        }
    
        //抛出异常Test成功
        @Test(expectedExceptions = NumberFormatException.class)
        public void testException2() {
            MathSolution.divide(1, 0);
        }
    }
    

    2.忽略测试

    如果某段代码还没有准备好去运行,那么先忽略它吧。

    public class IgnoreTest {
        @Test(enabled = false)
        public void ignoreTest() {
            System.out.println("被忽略的测试");
        }
    
        @Test
        public void noIgnoreTest() {
            System.out.println("不被忽略的测试");
        }
    }
    

    3.超时测试

    如果对测试代码有性能要求,那么请使用timeout吧。

    public class TimeOutTest {
        @Test(timeOut = 5000)
        public void testTimeOut() {
            LoopSolution.deadLoop();
        }
    
        @Test(invocationCount = 3, invocationTimeOut = 1000)
        public void testInvocation() {
            System.out.println("deadLoop");
            LoopSolution.sleepLoop();
        }
    
    }
    

    同时,如果想测试异步操作,也可以使用timeout。可以通过设置timeout超时时间、invocationCount调用次数、invocationTimeout调用超时总时间来测试异步操作。

    • 比如一个下单操作,之后要轮询是否下单成功。


      image.png
    • 但其实我们无法确定异步调用何时执行结束,无法确定异步调用需要多少次才能获取最终结果。使用时可以参考调用方的设置频率以及超时时间。
    public class TimeOutTest {
        @Test(timeOut = 5000)
        public void testTimeOut() {
            LoopSolution.deadLoop();
        }
    
        @Test(invocationCount = 3, invocationTimeOut = 1000)
        public void testInvocation() {
            System.out.println("deadLoop");
            LoopSolution.sleepLoop();
        }
    
        @Test(timeOut = 10000, invocationCount = 10)
        public void testFutureTask() {
            FutureSolution.getInt();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            assertThat(FutureSolution.IntegerNum, equalTo(5));
        }
    }
    

    三、多线程测试

    为什么要做多线程呢?节省时间呗。

    • 第一种方式是通过xml配置。
    <suite name="TestParallelSuite" parallel="classes" thread-count="5">
    
    parallel:
    methods:每个方法都将采用独立的线程进行测试
    tests:每个<test>标签内所有方法将在同一个线程中执行
    classes:每个<class>标签内所有方法在同一个线程中执行
    instances:同一个实例内所有方法运行在同一个线程中
    
    • 第二种方式通过定义@Test属性
    public class ParallelTest3 {
        @Test(threadPoolSize = 5, invocationCount = 10)
        public void testParallel() {
            System.out.println("Parallel3-threadId-" + Thread.currentThread().getId());
        }
    }
    

    四、TestNG监听器

    监听器在TestNG里非常常用,也很实用,当TestNG自带功能没办法满足我们的时候,监听器给了我们一种自定义的途径。

    常⽤的⼏种监听器,只需要实现⼀些接⼝,就可以更灵活的使⽤TestNG啦
    1.IAnnotationTransformer:修改@Test的属性
    2.IAnnotationTransformer2:修改@DataProvider、@Factory、@Configuration的属性
    3.IHookable:类似AOP,可以在测试⽅法执⾏前后提供切⼊点
    4.IInvokedMethodListener:与IHookable类似
    5.IReporter:⾃定义测试报告
    6.ISuiteListener:在suite执⾏前和结束后嵌⼊⾃⼰的逻辑
    7.ITestListener:在成功、失败、跳过时指定不同后续⾏为,简化IInvokedMethodListener

    listeners的使用方式:

    1. 在配置文件中使用
    <listeners>
       <!-- 监听器全路径 -->
        <listener class-name="com.example.MyListener1" /> 
        <listener class-name="com.example.MyListener2" />
    </listeners>
    
    1. 在源码中使用:
    • 在@Listeners中添加监听器,跟配置中添加⼀样,将被应⽤到整个测试套件中的测试⽅法,如果想使监听器只适⽤于某些测试类或者测试⽅法,需在监听器中编写逻辑。

    • @Listeners中不能添加IAnnotationTransformer和IAnnotationTransformer2 监听器。因为这两种监听器必须在更早的阶段添加到 TestNG 中才能实施修改注释的操作,所以它们只能在 testng.xml 添加。

    我比较常用的是IReporter和ITestListener这两个。

    IReporter可以用现有的库对TestNG的报告进行美化。

    ITestListener
    1.在测试⽅法成功、结束、跳过后,执⾏⼀些逻辑
    2.在<test>执⾏前后加⼀些逻辑
    3.extends TestListenerAdapter会简化你的代码
    4.一些入库、上报等等操作都可以在这里面实现

    //在测试⽅法开始前执⾏
    public void onTestStart(ITestResult result) {
    }
    //在测试⽅法成功后执⾏
    public void onTestSuccess(ITestResult result) {
    }
    //在测试⽅法失败后执⾏
    public void onTestFailure(ITestResult result) {
    }
    //在测试⽅法跳过后执⾏
    public void onTestSkipped(ITestResult result) {
    }
    //在测试⽅法失败但为百分⽐失败后执⾏
    public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
    }
    /**
     * testClass实例化之后、configuration⽅法调⽤之前执⾏
     * @param context
    */
    public void onStart(ITestContext context) {
    }
    /**
     * 所有测试⽅法执⾏结束之后执⾏
     * @param context
    */
    public void onFinish(ITestContext context) {
    } 
    

    感兴趣可以去我的github上下载代码,记得star哦~
    https://github.com/bingerlby/testngpro

    相关文章

      网友评论

        本文标题:TestNG系列-TestNG进阶

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