• testng TestListener 原理简析


    1. 在xmlSuite 解析 tag="listeners"的信息,加入addListener

    public class XmlSuite
    @OnElementList(tag = "listeners", attributes = { "class-name" })
    public void onListenerElement(String className) {
    addListener(className);
    }

    2.在运行test的时候,设置好不同运行状态(pass,failed)再运行 runTestListeners(testResult),同时把testresult传入

    private ITestResult invokeMethod(Object instance,
    final ITestNGMethod tm,
    Object[] parameterValues,
    int parametersIndex,
    XmlSuite suite,
    Map<String, String> params,
    ITestClass testClass,
    ITestNGMethod[] beforeMethods,
    ITestNGMethod[] afterMethods,
    ConfigurationGroupMethods groupMethods,
    FailureContext failureContext) {
    TestResult testResult = new TestResult();
    
    invokeBeforeGroupsConfigurations(testClass, tm, groupMethods, suite, params,
    instance);
    invokeConfigurations(testClass, tm,
    filterConfigurationMethods(tm, beforeMethods, true /* beforeMethods */),
    suite, params, parameterValues,
    instance, testResult);
    
    //
    // Create the ExtraOutput for this method
    //
    InvokedMethod invokedMethod = null;
    try {
    testResult.init(testClass, instance,
    tm,
    null,
    System.currentTimeMillis(),
    0,
    m_testContext);
    testResult.setParameters(parameterValues);
    testResult.setHost(m_testContext.getHost());
    testResult.setStatus(ITestResult.STARTED);
    
    invokedMethod= new InvokedMethod(instance,
    tm,
    parameterValues,
    System.currentTimeMillis(),
    testResult);
    
    // Fix from ansgarkonermann
    // invokedMethod is used in the finally, which can be invoked if
    // any of the test listeners throws an exception, therefore,
    // invokedMethod must have a value before we get here
    runTestListeners(testResult);
    
    runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult);
    
    m_notifier.addInvokedMethod(invokedMethod);
    
    Method thisMethod = tm.getConstructorOrMethod().getMethod();
    
    if(confInvocationPassed(tm, tm, testClass, instance)) {
    log(3, "Invoking " + tm.getRealClass().getName() + "." + tm.getMethodName());
    
    Reporter.setCurrentTestResult(testResult);
    
    // If this method is a IHookable, invoke its run() method
    IHookable hookableInstance =
    IHookable.class.isAssignableFrom(tm.getRealClass()) ?
    (IHookable) instance : m_configuration.getHookable();
    
    if (MethodHelper.calculateTimeOut(tm) <= 0) {
    if (hookableInstance != null) {
    MethodInvocationHelper.invokeHookable(instance,
    parameterValues, hookableInstance, thisMethod, testResult);
    } else {
    // Not a IHookable, invoke directly
    MethodInvocationHelper.invokeMethod(thisMethod, instance,
    parameterValues);
    }
    testResult.setStatus(ITestResult.SUCCESS);
    } else {
    // Method with a timeout
    MethodInvocationHelper.invokeWithTimeout(tm, instance, parameterValues, testResult, hookableInstance);
    }
    }
    else {
    testResult.setStatus(ITestResult.SKIP);
    }
    }
    catch(InvocationTargetException ite) {
    testResult.setThrowable(ite.getCause());
    testResult.setStatus(ITestResult.FAILURE);
    }
    catch(ThreadExecutionException tee) { // wrapper for TestNGRuntimeException
    Throwable cause= tee.getCause();
    if(TestNGRuntimeException.class.equals(cause.getClass())) {
    testResult.setThrowable(cause.getCause());
    }
    else {
    testResult.setThrowable(cause);
    }
    testResult.setStatus(ITestResult.FAILURE);
    }
    catch(Throwable thr) { // covers the non-wrapper exceptions
    testResult.setThrowable(thr);
    testResult.setStatus(ITestResult.FAILURE);
    }
    finally {
    // Set end time ASAP
    testResult.setEndMillis(System.currentTimeMillis());
    
    ExpectedExceptionsHolder expectedExceptionClasses
    = new ExpectedExceptionsHolder(m_annotationFinder, tm, new RegexpExpectedExceptionsHolder(m_annotationFinder, tm));
    List<ITestResult> results = Lists.<ITestResult>newArrayList(testResult);
    handleInvocationResults(tm, results, expectedExceptionClasses, failureContext);
    
    // If this method has a data provider and just failed, memorize the number
    // at which it failed.
    // Note: we're not exactly testing that this method has a data provider, just
    // that it has parameters, so might have to revisit this if bugs get reported
    // for the case where this method has parameters that don't come from a data
    // provider
    if (testResult.getThrowable() != null && parameterValues.length > 0) {
    tm.addFailedInvocationNumber(parametersIndex);
    }
    
    //
    // Increment the invocation count for this method
    //
    tm.incrementCurrentInvocationCount();
    
    // Run invokedMethodListeners after updating TestResult
    runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult);
    runTestListeners(testResult);
    
    //
    // Invoke afterMethods only if
    // - lastTimeOnly is not set
    // - lastTimeOnly is set, and we are reaching the last invocationCount
    //
    invokeConfigurations(testClass, tm,
    filterConfigurationMethods(tm, afterMethods, false /* beforeMethods */),
    suite, params, parameterValues,
    instance,
    testResult);
    
    //
    // Invoke afterGroups configurations
    //
    invokeAfterGroupsConfigurations(testClass, tm, groupMethods, suite,
    params, instance);
    
    // Reset the test result last. If we do this too early, Reporter.log()
    // invocations from listeners will be discarded
    Reporter.setCurrentTestResult(null);
    }

    3.通过testresult的状态分别调用 testlistener的各种方法(onstart,onfailed....),支持多个ITestListener噢

    public static void runTestListeners(ITestResult tr, List<ITestListener> listeners) {
    for (ITestListener itl : listeners) {
    switch(tr.getStatus()) {
    case ITestResult.SKIP: {
    itl.onTestSkipped(tr);
    break;
    }
    case ITestResult.SUCCESS_PERCENTAGE_FAILURE: {
    itl.onTestFailedButWithinSuccessPercentage(tr);
    break;
    }
    case ITestResult.FAILURE: {
    itl.onTestFailure(tr);
    break;
    }
    case ITestResult.SUCCESS: {
    itl.onTestSuccess(tr);
    break;
    }
    
    case ITestResult.STARTED: {
    itl.onTestStart(tr);
    break;
    }
    
    default: {
    assert false : "UNKNOWN STATUS:" + tr;
    }
    }
    }
    }
    
    return testResult;
    }
  • 相关阅读:
    Git命令branch-分支
    Git基础命令(二)
    Git基础命令(一)
    【转载】Android状态栏微技巧,带你真正理解沉浸式模式
    Android性能分析工具
    【转载】Android卡顿检测方案
    WebView loadData中文乱码
    【Cocos2dx】新建场景、场景的切换、设置启动场景与菜单的新建
    Cocos2d-JS切换场景与切换特效
    COCOS2DX场景切换特效
  • 原文地址:https://www.cnblogs.com/season-xie/p/7811363.html
Copyright © 2020-2023  润新知