#unit-testing #testing #junit #junit4
#модульное тестирование #тестирование #junit #junit4
Вопрос:
Для выполнения автоматических тестов пользовательского интерфейса я запускаю тесты на внешнем облачном сервисе, для которого требуется загрузка нашего набора тестов (для целей этого вопроса, пожалуйста, рассмотрите их подход как данность).
Я все еще хочу, чтобы этот процесс был инкапсулирован в JUnit runner, чтобы быть совместимым с запусками, использующими различные облачные сервисы или локальное выполнение. Я выполняю свои тесты с помощью 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:
По сути, с одним результатом теста 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
.
Комментарии:
1. Спасибо, что указали на
Unrooted tests
проблему. Я тоже столкнулся с этим, следовало включить это в мой первоначальный вопрос.