JUnit测试运行器方法过滤

时间:2020-03-31 10:57:22

标签: java junit

我正在创建自己的测试运行器,以介绍对多个测试注释,依赖项注入和自定义初始化的支持。我以为我的测试看起来会更干净,但是我在描述测试时遇到了问题。

我有注释@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对象引起的。有没有正确的方法来更新该过滤器?

0 个答案:

没有答案
相关问题