Вручную создайте объект JUnit Result - PullRequest
4 голосов
/ 25 апреля 2019

Для выполнения автоматических тестов пользовательского интерфейса я запускаю тесты на внешней облачной службе, которая требует загрузки нашего набора тестов (для целей этого вопроса, пожалуйста, примите во внимание их подход).

Я все еще хочу, чтобы этот процесс был инкапсулирован в бегун 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 предлагает методы типа fireTestFinished или fireTestFailure, но яне знаете, как строить объекты (Result, Description, Failure), эти методы принимают в качестве параметров.Я подозреваю, что мне нужно использовать тестовых слушателей, но я не могу выяснить детали.

В более широком смысле, каковы мои варианты для создания результатов теста 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)?Я могу придумать несколько хакерских способов, но я уверен, что есть правильный.

1 Ответ

1 голос
/ 01 мая 2019

По сути, с одним результатом теста 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, который обычно требуется).

Дошло до сборки 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.

...