testng-failed.xml不包含always run = true的方法

时间:2017-12-21 11:19:34

标签: testng

假设我有两个班级

Class A
{
     @BeforeClass
     public void abc()
     {
        ----
     }
     @Test(alwaysRun = true)
     public void def()
     {
        -----
     }
}

另一个班级

Class B
{
    @Test
    public void xyz()
    {
         SoftAssert sa = new SoftAssert();
         -----
         sa.fail();
         sa.assertAll();
    }
}

让我们说B级失败了 然后testng-failed.xml将按如下方式进行操作

<test name="test1(failed)">
<classes>
  <class name="A">
    <methods>
      <include name="abc"/>
    </methods>
  </class>

   <class name="B">
    <methods>
      <include name="xyz"/>
    </methods>
  </class>    

我已经提到,如果方法def为true,那么run = true,那么该方法也必须包含在testng-failed.xml中。

为什么testng-failed.xml中没有?

1 个答案:

答案 0 :(得分:0)

根据alwaysRun方法定义@Test属性表示以下内容(引用javadoc)

  

如果设置为true,则即使它依赖,也始终运行此测试方法   关于失败的方法。

根据行为,TestNG仅包含testng-failed.xml中失败的那些方法。因此,如果您的def()方法没有失败,那么它就不会包含在您的testng-failed.xml中。

如果您希望始终包含def()方法(然后我猜测,它不是@Test方法,但似乎更像是一种配置方法),那么你有以下选项。

  1. 将其移出@Test方法(因为它看起来确实不是一种测试方法,而是某种条件设置,只需要对某些方法进行)和一个TestNG监听器[for例如,org.testng.IInvokedMethodListener]并且在侦听器内根据某些自定义注释执行此操作。因此,需要运行此特殊代码段的所有方法都会添加自定义注释[请参阅here示例] 在这个监听器的beforeInvocation()中你会找到自定义注释,如果找到,你就可以运行它。

  2. 另一个选项基本上是让这部分基类实现org.testng.IHookable接口。所有的测试方法都会扩展这个基类,并通过IHookable接口扩展基类[run()方法的run()实现],你可以添加我上面提到的相同的自定义注释逻辑。

  3. 这是一个展示所有这些内容的示例。

    (1)的样本

    标记注释。

    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.ElementType.METHOD;
    
    /**
     * A marker annotation that indicates a special setup is needed.
     */
    @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
    @Target({METHOD})
    public @interface NeedSpecialSetup {}
    
    /**
     * This interface which when implemented by test classes (classes that hold one or more {@link org.testng.annotations.Test}
     * annotated methods lets you perform special actions. But the methods should also be annotated using {@link NeedSpecialSetup}
     * annotation for this implementation to be invoked.
     */
    public interface PerformSpecialSetup {
        void perform();
    }
    

    听众

    import org.testng.IInvokedMethod;
    import org.testng.IInvokedMethodListener;
    import org.testng.ITestResult;
    
    public class SimpleMethodListener implements IInvokedMethodListener {
        @Override
        public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
            //Did the method have our custom annotation which indicates that special setup is needed ?
            NeedSpecialSetup specialsetup = method.getTestMethod().getConstructorOrMethod().getMethod().getAnnotation(NeedSpecialSetup.class);
            if (specialsetup != null) {
                //Now lets check if the Object to which the method belongs to, has the capability to do the special setup
                //and if it does, just delegate the call back to the respective test class instance. This way, we are not
                //hard wiring any logic to our listener, but letting the respective test classes do whatever custom
                //setup it requires.
                Object instance = testResult.getInstance();
                if (instance instanceof PerformSpecialSetup) {
                    ((PerformSpecialSetup) instance).perform();
                }
            }
        }
    
        @Override
        public void afterInvocation(IInvokedMethod method, ITestResult testResult) { }
    }
    

    测试类

    import org.testng.annotations.Listeners;
    import org.testng.annotations.Test;
    
    @Listeners(SimpleMethodListener.class)
    public class MyTestClass implements PerformSpecialSetup {
    
        @Test
        public void method1() {
            System.err.println("method1() invoked");
        }
    
        @Test
        @NeedSpecialSetup
        public void method2() {
            System.err.println("method2() invoked");
        }
    
        @Override
        public void perform() {
            System.err.println("Special setup completed");
        }
    }
    

    (2)的样本

    import org.testng.IHookCallBack;
    import org.testng.IHookable;
    import org.testng.ITestResult;
    import org.testng.annotations.Test;
    
    public class AnotherTestClass implements IHookable {
        @Override
        public void run(IHookCallBack callBack, ITestResult testResult) {
            NeedSpecialSetup specialsetup = testResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(NeedSpecialSetup.class);
            if (specialsetup != null) {
                perform();
            }
            callBack.runTestMethod(testResult);
        }
    
        @Test
        public void method1() {
            System.err.println("method1() invoked");
        }
    
        @Test
        @NeedSpecialSetup
        public void method2() {
            System.err.println("method2() invoked");
        }
    
        public void perform() {
            System.err.println("Special setup completed");
        }
    }