考虑以下测试类:
<strong i="6">@Test</strong>
public abstract class ParentTest {
public void parentTestMethod() {
}
}
@Test(groups = "myGroup")
public class ChildTest extends ParentTest {
public void childTestMethod() {
}
}
运行此测试 (ChildTest) 时,我希望两个测试方法(childTestMethod 和 parentTestMethod)都属于“myGroup”组。 显然这不是实际行为(用 6.4 版测试)。
我整理了一些代码来调查这个问题:
TestNGMethodFinder testNGMethodFinder = new TestNGMethodFinder(new RunInfo(), new JDK15AnnotationFinder(new DefaultAnnotationTransformer()));
ITestNGMethod[] testMethods = testNGMethodFinder.getTestMethods(ChildTest.class, new XmlTest());
for (ITestNGMethod testMethod : testMethods) {
String[] groups = testMethod.getGroups();
System.out.println(testMethod + " groups:" + Arrays.toString(groups));
}
运行此代码的输出:
ChildTest.childTestMethod()[pri:0, instance:null] groups:[myGroup]
ParentTest.parentTestMethod()[pri:0, instance:null] groups:[]
我查看了 TestNG 源代码,似乎这种行为源自方法 org.testng.internal.BaseTestMethod#initGroups(Class>)。 确切地说,我认为以下语句是导致这种相当奇怪的行为的原因:
ITestOrConfiguration classAnnotation = (ITestOrConfiguration) getAnnotationFinder().findAnnotation(getMethod().getDeclaringClass(), annotationClass);
为了解决这个问题,这个语句可以修改为:
ITestOrConfiguration classAnnotation = (ITestOrConfiguration) getAnnotationFinder().findAnnotation(getInstance().getClass(), annotationClass);
但我不确定这是否是解决问题的正确方法。 也没有最终的影响......
我看到了这个问题,不幸的是,你的建议并不奏效。 解决起来有点棘手,因为注解是在init阶段解决的,这意味着当解析父的@Test注解时,它显然对子注解会向其添加更多组的事实一无所知......
塞德里克,感谢您对这个问题的及时反馈。 你说“有点难解决”,是不是说你不认为这个问题近期有解决的可能? 你能想出任何可能的解决方法吗?
我的意思是:当执行组解析时,还没有实例化测试类,所以当我查看 parentTestMethod() 时,我没有一个 ChildTest 实例可以让我将该方法放在这个组中。
组解析是纯静态的,而上面的例子只能动态解析。
这有意义吗?
我也见过这种行为。 当我在没有组过滤器的情况下运行我的测试时,一切都通过了,但是当与组一起运行时,事情会失败。 在某些情况下,这是由于我的测试类继承了其他一些测试类,但在其他情况下,我有 POJO 测试类,并且似乎我的@BeforeMethod
和@AfterMethod
方法没有正确调用。
顺便说一句,我的解决方案是使用excludedgroups,这当然不适用于所有情况。 @cbeust ,是否有任何针对此问题的适当解决方案的工作?
一年多后,这仍然不起作用。
@cbeust恕我直言,这没有任何意义:由于父类是抽象的,因此其组解析应基于测试类的具体实例。
FWIW 我也遇到了这个问题。
我创建了一个自定义方法选择器,它使用子类 Test annoation 中的组
/* *****************************************************************************
* Copyright 2017 VMware, Inc. All rights reserved. VMware Confidential
* ****************************************************************************/
package com.vmware.cloud.systemtests.util;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.testng.IMethodSelector;
import org.testng.IMethodSelectorContext;
import org.testng.ITestNGMethod;
import org.testng.annotations.Test;
import org.testng.xml.XmlTest;
/**
* Selector that uses groups in subclass <strong i="6">@Test</strong> annotations to determine if methods should be included
*/
public class SubclassAwareXmlMethodsSelector implements IMethodSelector {
<strong i="7">@Override</strong>
public boolean includeMethod(IMethodSelectorContext context, ITestNGMethod method, boolean isTestMethod) {
XmlTest xmlTest = method.getXmlTest();
if (xmlTest == null) {
return method.isAlwaysRun();
}
Class realTestClass = isTestMethod ? method.getTestClass().getRealClass() : method.getRealClass();
Test testClassAnnotation = (Test) realTestClass.getAnnotation(Test.class);
String[] classAnnotationGroups = testClassAnnotation != null ? testClassAnnotation.groups() : new String[0];
List<String> groups = Arrays.asList(ArrayUtils.addAll(classAnnotationGroups, method.getGroups()));
context.setStopped(true);
if (groups.size() == 0 && xmlTest.getIncludedGroups().isEmpty()) {
return true;
} else if (groups.size() > 0 && xmlTest.getExcludedGroups().stream().anyMatch(groups::contains)) {
return false;
} else if (groups.size() > 0 && xmlTest.getIncludedGroups().stream().anyMatch(groups::contains)) {
return true;
} else {
return method.isAlwaysRun();
}
}
<strong i="8">@Override</strong>
public void setTestMethods(List<ITestNGMethod> list) {
}
}