【问题标题】:Manually create a JUnit Result object手动创建 JUnit Result 对象
【发布时间】:2019-04-25 06:03:18
【问题描述】:

为了执行自动化 UI 测试,我在 an external cloud service which requires the upload of our test suite 上触发测试(就本问题而言,请考虑他们的方法)。

我仍然希望将此过程封装到 JUnit 运行器中,以与使用不同云服务或本地执行的运行保持一致。我使用 Maven 执行测试

mvn clean install -Dtest=TestRunner -Dproperties=/path/to/settings.file

无论使用哪个测试提供者,我都希望这个流程保持一致。

我想出的解决方法是在我的本地机器上触发这样的测试

@Override
public void run(RunNotifier notifier) {
  if (someCondition) {
    new DelegateRunner().run(notifier);
  } else {
    super.run(notifier);
  }
}

DelegateRunner 然后调用第三方服务,触发云端测试。如何将我从该服务收到的结果(我可以查询他们的 API)映射回我的本地 JUnit 执行?

RunNotifier 类提供 fireTestFinishedfireTestFailure 之类的方法,但我不确定如何构建对象(ResultDescriptionFailure)这些方法作为参数。我怀疑我需要使用测试侦听器,但我无法弄清楚细节。

从更广泛的意义上说,当实际测试在远程机器上运行或什至不作为 JUnit 测试执行时,我有哪些选择来创建 JUnit 测试结果?这是有人以前遇到过的用例吗?它可能有点异国情调,但我不认为我是第一个。

首先,我只想提供一个二进制结果 - 测试通过或至少一个测试失败 - 以一种不会破坏任何 JUnit 集成的方式(如 Maven surefire 插件)。

现在,我明白了:

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 501.287 sec

No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.)

如果测试失败,我如何才能使构建失败并通过其他方式(测试数为 1)?我能想到一些 hacky 方法,但我确信有一个合适的方法。

【问题讨论】:

    标签: unit-testing testing junit junit4


    【解决方案1】:

    在最基本的情况下,只有一个测试结果,DelegateRunner 可能是这样的:

    public class DelegateRunner extends Runner {
    
        private Description testDescription = Description
                .createTestDescription("groupName", "testName");
    
        public DelegateRunner(Class<?> testClass) {
        }
    
        @Override
        public Description getDescription() {
            return testDescription;
        }
    
        @Override
        public void run(RunNotifier notifier) {
            notifier.fireTestStarted(testDescription);
            ... trigger remote test ...
            if (passed)
                notifier.fireTestFinished(testDescription);
            else
                notifier.fireTestFailure(new Failure(testDescription,
                        new AssertionError("Details of the failure")));
        }
    
    }
    

    那么getDescription()run() 都需要被包装:

    public class FrontRunner extends Runner {
        private Runner runner;
    
        public FrontRunner(Class<?> testClass) throws InitializationError {
            if (someCondition)
                runner = new DelegateRunner(testClass);
            else
                runner = new JUnit4(testClass);
        }
    
        @Override
        public Description getDescription() {
            return runner.getDescription();
        }
    
        @Override
        public void run(RunNotifier notifier) {
            runner.run(notifier);
        }
    }
    

    (假设可以预先知道someCondition,并且它只是通常需要的默认JUnit4 runner)。

    这如预期的那样通过 Maven 构建:

    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running ...FrontRunnerTest
    Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.078 sec <<< FAILURE!
    testName(groupName)  Time elapsed: 0.015 sec  <<< FAILURE!
    java.lang.AssertionError: Details of the failure
            at so.ownrunner.DelegateRunner.run(DelegateRunner.java:28)
            at so.ownrunner.FrontRunner.run(FrontRunner.java:27)
            at ...
    
    Results :
    
    Failed tests:   testName(groupName): Details of the failure
    
    Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
    

    如果需要更结构化的响应,Description.addChild() 可用于嵌套套件和/或测试,例如:

    public class NestedDelegateRunner extends Runner {
    
        private Description suiteDescription = Description
                .createSuiteDescription("groupName");
        private Description test1Description = Description
                .createTestDescription("groupName", "test1");
        private Description test2Description = Description
                .createTestDescription("groupName", "test2");
    
        public NestedDelegateRunner(Class<?> testClass) {
            suiteDescription.addChild(test1Description);
            suiteDescription.addChild(test2Description);
        }
    
        @Override
        public Description getDescription() {
            return suiteDescription;
        }
    
        @Override
        public void run(RunNotifier notifier) {
            notifier.fireTestStarted(test1Description);
            notifier.fireTestStarted(test2Description);
    
            notifier.fireTestFinished(test1Description);
            notifier.fireTestFailure(new Failure(test2Description,
                    new AssertionError("Details of the failure")));
        }
    
    }
    

    事实上addChild() 并不重要,但没有它,结构可能不太明显 - 例如像 Eclipse 这样的东西只会显示Unrooted tests

    【讨论】:

    • 感谢您指出Unrooted tests 问题。我也遇到了这个问题,应该将它包含在我原来的问题中。
    猜你喜欢
    • 2017-10-30
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2021-11-17
    相关资源
    最近更新 更多