美文网首页
Testng(二):监听

Testng(二):监听

作者: halfempty | 来源:发表于2018-11-11 15:28 被阅读0次

    1 概述

    监听(Listeners),捕捉Testng的行为,并支持修改,用于定制化,如日志输出、自定义报告

    监听器如下:

    • IAnnotationTransformer,只支持@Test注解转换
    • IAnnotationTransformer2,支持@Test,@DataProvider,@Factory等注解转换,比第一代更全面
    • IHookable,替代@Test测试方法,并提供回调函数,常用于权限校验
    • IInvokedMethodListener/IInvokedMethodListener2,监听before/after形为,2代增加上下文参数
    • IMethodInterceptor,拦截器,调整测试方法的执行顺序
    • IReporter,suit执行完成后生成报告
    • ISuiteListener,测试套件执行监听
    • ITestListener,测试方法执行监听

    2 IAnnotationTransformer

    实现IAnnotationTransformer的transform方法

    参数含义:

    • ITestAnnotation,即@Test注解本身,可以修改它的各种属性,如dataProvider,enabled,invocationCount等
    • Class,当@Test应用于class时,指向当前类;否则值为null
    • Constructor,同上,作用对象为构造器
    • Method,同上,作用对象为方法

    需求:以2结尾的方法执行2次

    public class MyTransformer implements IAnnotationTransformer {
        @Override
        public void transform(ITestAnnotation iTestAnnotation, Class aClass, Constructor constructor, Method method) {
            if (method.getName().endsWith("2")) {
                iTestAnnotation.setInvocationCount(2);
            }
        }
    }
    
    public class App {
    
        @Test
        public void test_1() {
            System.out.println("Just run once");
        }
    
        @Test
        public void test_2() {
            System.out.println("Run twice");
        }
    }
    ---------------------------
    Just run once
    Run twice
    Run twice
    

    testng.xml配置

    <suite name="Suite1" verbose="1" >
        <listeners>
            <listener class-name="MyTransformer"/>
        </listeners>
    
        <test name="Test1">
            <classes>
                <class name="App" />
            </classes>
        </test>
    </suite>
    

    @Listeners不支持IAnnotationTransformer 和 IAnnotationTransformer2,所以只能在testng.xml上配置监听器,当然命令行也可行

    3 IHookable

    实现IHookable的run方法

    调用IHookCallBack的runTestMethod方法,可以回调原测试方法

    需求:只执行以2结尾的方法

    public class MyHookable implements IHookable {
    
        @Override
        public void run(IHookCallBack callBack, ITestResult testResult) {
            if (testResult.getMethod().getMethodName().endsWith("2")) {
                callBack.runTestMethod(testResult);
            }
        }
    }
    
    @Listeners({MyHookable.class})
    public class App {
    
        @Test
        public void test_1() {
            System.out.println("Just run once");
        }
    
        @Test
        public void test_2() {
            System.out.println("Run twice");
        }
    }
    -----------------------------
    Run twice
    

    4 IInvokedMethodListener

    适用于configuration(suit, test, class),以及test

    配合log4j,可以记录详细的执行过程

    public class MyInvokedMethodListener implements IInvokedMethodListener {
        @Override
        public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
            System.out.println("begin to run " + testResult.getName());
        }
    
        @Override
        public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
            System.out.println("end to run " + testResult.getName() + ", result code is " + testResult.getStatus());
        }
    }
    
    @Listeners({MyInvokedMethodListener.class})
    public class App {
    
        @BeforeClass
        public void setup() {
            System.out.println("initial env");
        }
    
        @Test
        public void test_1() {
            System.out.println("test 1");
            Assert.assertTrue(true);
        }
    
        @Test
        public void test_2() {
            System.out.println("test 2");
            Assert.assertTrue(false);
        }
    }
    ---------------------
    begin to run setup
    initial env
    end to run setup, result code is 1
    begin to run test_1
    test 1
    end to run test_1, result code is 1
    begin to run test_2
    test 2
    end to run test_2, result code is 2
    

    5 IMethodInterceptor

    需求:优先执行fast组成员方法

    public class MyMethodInterceptor implements IMethodInterceptor {
        @Override
        public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
            List<IMethodInstance> result = new ArrayList<>();
    
            methods.forEach(method -> {
                Test test = method.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class);
                Set<String> groups = new HashSet<>();
                Arrays.stream(test.groups()).forEach(group -> groups.add(group));
    
                if (groups.contains("fast")) {
                    result.add(0, method);
                } else {
                    result.add(method);
                }
            });
            return result;
        }
    }
    
    public class App {
    
        @Test
        public void test_1() {
            System.out.println("first to run");
        }
    
        @Test(groups = {"fast"})
        public void test_2() {
            System.out.println("second to run");
        }
    
        @Test void test_3() {
            System.out.println("third to run");
        }
    }
    ---------------------------------
    second to run
    first to run
    third to run
    

    6 ISuiteListener

    覆写onStart 和 onFinish方法,分别对应suite开始阶段和结束阶段

    7 ITestListener

    对应测试方法的7种状态:

    • onStart,测试类实例化后执行
    • onFinish,测试类下的所有测试方法完成后执行
    • onTestStart,每次执行测试方法前执行
    • onTestSuccess,每次测试方法执行成功后执行
    • onTestFailure,每次测试方法执行失败后执行
    • onTestSkipped,每次测试方法跳过时执行
    • onTestFailedButWithinSuccessPercentage,每次测试方法执行失败,但正确率符合successPercentage要求

    实现ITestListener接口,需要覆写上述7种方法,比较麻烦

    因此实际偏向于继承TestListenerAdapter

    7 IReporter

    获取testng执行结果,与html模板结合可以定制测试报告

    public class MyReporter implements IReporter {
        @Override
        public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
            suites.forEach(suite -> {
                System.out.println("测试方法如下:");
                suite.getAllMethods().forEach(iTestNGMethod -> System.out.println("\t" + iTestNGMethod.getMethodName()));
    
                System.out.println("报告输出路径:" + suite.getOutputDirectory());
    
                suite.getResults().values().forEach(iSuiteResult -> {
                    ITestContext iTestContext = iSuiteResult.getTestContext();
    
                    Set<ITestResult> passedTests = iTestContext.getPassedTests().getAllResults();
                    System.out.println("执行成功的方法:" + passedTests.size());
                    passedTests.forEach(iTestResult -> {
                        System.out.println("\t" + iTestResult.getName());
                        System.out.println("\t\t开始时间:" + iTestResult.getStartMillis());
                        System.out.println("\t\t结束时间:" + iTestResult.getEndMillis());
                    });
    
                    Set<ITestResult> failedTests = iTestContext.getFailedTests().getAllResults();
                    System.out.println("执行失败的方法:" + failedTests.size());
                    failedTests.forEach(iTestResult -> {
                        System.out.println("\t" + iTestResult.getName());
                        System.out.println("\t\t开始时间:" + iTestResult.getStartMillis());
                        System.out.println("\t\t结束时间:" + iTestResult.getEndMillis());
                    });
                });
            });
        }
    }
    
    @Listeners({MyReporter.class})
    public class App {
    
        @Test
        public void test_1() {
            System.out.println("first to run");
        }
    
        @Test
        public void test_2() {
            System.out.println("second to run");
        }
    
        @Test
        public void test_3() {
            Assert.assertTrue(false);
        }
    }
    ------------------------
    测试方法如下:
        test_1
        test_2
        test_3
    报告输出路径:E:\code\java\lab\test-output\Default Suite
    执行成功的方法:2
        test_2
            开始时间:1541921094204
            结束时间:1541921094204
        test_1
            开始时间:1541921094188
            结束时间:1541921094188
    执行失败的方法:1
        test_3
            开始时间:1541921094204
            结束时间:1541921094204
    

    相关文章

      网友评论

          本文标题:Testng(二):监听

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