可以说我有两节课
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中没有这个?
根据定义,alwaysRun
方法的@Test
属性表示以下内容(引用javadocs)
如果设置为true,则即使依赖于失败的方法,也始终会运行此测试方法。
根据行为,TestNG仅包括那些在testng-failed.xml
中失败的方法。因此,如果你的def()
方法没有失败,那么它就不会被包含在你的testng-failed.xml
中。
如果你想要始终包含def()
方法(然后猜测,它不是@Test
方法,但似乎更像是一种配置方法),那么你有以下选择。
org.testng.IInvokedMethodListener
]和在侦听器中,基于某些自定义注释执行此操作。因此,所有需要运行此特殊代码片段的方法都会添加自定义注释[请参阅here示例],在此侦听器的beforeInvocation()
中,您将查找自定义注释,如果找到,则运行它。org.testng.IHookable
接口的基类的这一部分。所有的测试方法都会扩展这个基类,并且通过IHookable接口在基类[run()方法的run()实现中)你会添加我上面提到的相同的自定义注释逻辑。这是一个展示所有这些内容的示例。
样品(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");
}
}