我正在创建自己的测试运行器,以介绍对多个测试注释,依赖项注入和自定义初始化的支持。我以为我的测试看起来会更干净,但是我在描述测试时遇到了问题。
我有注释@RunAgainst
和@RunAgainstConfig
,可以按如下方式使用
@Test
@RunAgainst({
@RunAgainstConfig(
deviceType = DeviceType.ANDROID_GENERIC,
applicationFlavour = ApplicationFlavour.MAIN
),
@RunAgainstConfig(
deviceType = DeviceType.ANDROID_US,
applicationFlavour = ApplicationFlavour.SOME_OTHER
)
})
public void testMethod() {...}
因此,如果您指定多个@RunAgainstConfig
,则将针对多个配置执行单个测试作为单独的测试。
这是我的测试跑步者:
public class MyTestRunner extends ParentRunner<TestDescriptor> {
private static final Logger logger = LoggerFactory.getLogger(MyTestRunner.class);
private static final int MAX_ATTEMPTS = 2;
private Class testClass;
private Object testObject;
public MyTestRunner(Class testClass) throws InitializationError {
super(testClass);
this.testClass = testClass;
try {
this.testObject = testClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new InitializationError(new Exception("Failed to initialize the class " + testClass.getCanonicalName(), e));
}
}
@Override
protected List<TestDescriptor> getChildren() {
List<TestDescriptor> result = new ArrayList<>();
for (Method method : testClass.getDeclaredMethods()) {
if (!method.isAnnotationPresent(Test.class)) {
continue;
}
if (!method.isAnnotationPresent(RunAgainst.class)) {
throw new RuntimeException("Add the " + RunAgainst.class.getCanonicalName() + " annotation to define the runtime environment");
}
for (RunAgainstConfig config : method.getAnnotation(RunAgainst.class).value()) {
result.add(new TestDescriptor(
config.deviceType(),
config.applicationFlavour(),
method
));
}
}
return result;
}
private String getTestName(TestDescriptor config) {
return config.getMethod()
+ " ["
+ config.getDeviceType()
+ ", "
+ config.getApplicationFlavour()
+ "]";
}
@Override
protected Description describeChild(TestDescriptor config) {
return Description.createTestDescription(testClass, getTestName(config), config.getMethod().getAnnotations());
}
@Override
protected void runChild(TestDescriptor config, RunNotifier notifier) {
logger.info("Running test for " + config);
Description description = describeChild(config);
EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
eachNotifier.fireTestStarted();
try {
tryRunTest(config);
} catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
} catch (Throwable e) {
eachNotifier.addFailure(e);
} finally {
eachNotifier.fireTestFinished();
}
}
private void tryRunTest(TestDescriptor config) {
for (int i = 0; i < MAX_ATTEMPTS; i++) {
AndroidDriver driver = getAndroidDriver(config.getDeviceType(), config.getApplicationFlavour());
DependencyInjector dependencyInjector = new DependencyInjector(Arrays.asList(
config.getDeviceType(),
config.getApplicationFlavour(),
Configuration.getDeviceConfig(config.getDeviceType()),
driver
));
try {
TestExecutionContext.runInContext(buildTestExecutionContext(driver, config), () -> {
config.getMethod().invoke(testObject, dependencyInjector.getDependencies(config.getMethod()));
});
break;
} catch (Exception e) {
logger.warn("Attempt (" + (i + 1) + ") to run the test " + config.getMethod().getName() + " failed");
} finally {
driver.quit();
}
}
}
private Context buildTestExecutionContext(AndroidDriver driver, TestDescriptor configuration) {
return new Context(
Configuration.getDeviceConfig(configuration.getDeviceType()),
configuration.getDeviceType(),
configuration.getApplicationFlavour(),
driver
);
}
}
现在,问题与Description.createTestDescription
有关。通常,作为第二个参数,我应该提供测试方法,但是由于我以相同的名称进行了两次测试而最终不太理想。我希望该名称指示用于特定运行的配置,因此我介绍了getTestName
。但这就像一种魅力,但是,现在当我想运行一个测试时,我得到了一个异常
java.lang.Exception: No tests found matching Method runSingInBySmsExistingProfileTest(com.app.android.SignInPhoneTests) from org.junit.internal.requests.ClassRequest@ca263c2
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:40)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
这是由于传递给Filter
的无效ParentRunner.filter
对象引起的。有没有正确的方法来更新该过滤器?