Перейти к основному содержимому

JUnit 5 API TestWatcher

· 5 мин. чтения

1. Обзор

При модульном тестировании мы можем периодически обрабатывать результаты выполнения наших тестовых методов. В этом кратком руководстве мы рассмотрим, как это можно сделать с помощью TestWatcher API, предоставляемого JUnit .

Чтобы получить подробное руководство по тестированию с помощью JUnit, ознакомьтесь с нашим превосходным руководством по JUnit 5 .

2. API TestWatcher

Короче говоря, интерфейс TestWatcher определяет API для расширений , которые хотят обрабатывать результаты тестов . Один из способов, которым мы можем думать об этом API, — это предоставление хуков для получения статуса отдельного тестового примера.

Но, прежде чем мы углубимся в некоторые реальные примеры, давайте сделаем шаг назад и кратко подытожим методы в интерфейсе TestWatcher :

testAborted​(ExtensionContext context, Throwable cause)

Чтобы обработать результаты прерванного теста, мы можем переопределить метод testAborted . Как следует из названия, этот метод вызывается после прерывания теста.

testDisabled​(ExtensionContext context, Optional reason)

Мы можем переопределить метод testDisabled , когда хотим обработать результаты отключенного метода тестирования. Этот метод также может включать в себя причину отключения теста.

testFailed(ExtensionContext context, Throwable cause)

Если мы хотим выполнить некоторую дополнительную обработку после сбоя теста, мы можем просто реализовать функциональность в методе testFailed . Этот метод может включать в себя причину отказа теста.

testSuccessful(ExtensionContext context)

И последнее, но не менее важное: когда мы хотим обработать результаты успешного теста, мы просто переопределяем метод testSuccessful .

Следует отметить, что все методы содержат ExtensionContext . Это инкапсулирует контекст, в котором выполняется текущий тест.

3. Зависимости Maven

Прежде всего, давайте добавим зависимости проекта, которые нам понадобятся для наших примеров.

Помимо основной библиотеки JUnit 5 junit-jupiter-engine , нам также понадобится библиотека junit- jupiter-api :

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>

Как всегда, последнюю версию мы можем получить с Maven Central .

4. Пример TestResultLoggerExtension

Теперь, когда у нас есть общее представление об API TestWatcher , мы рассмотрим практический пример.

Давайте начнем с создания простого расширения для регистрации результатов и предоставления сводки наших тестов . В этом случае для создания расширения нам нужно определить класс, реализующий интерфейс TestWatcher :

public class TestResultLoggerExtension implements TestWatcher, AfterAllCallback {
private List<TestResultStatus> testResultsStatus = new ArrayList<>();

private enum TestResultStatus {
SUCCESSFUL, ABORTED, FAILED, DISABLED;
}

//...
}

Как и все интерфейсы расширения, интерфейс TestWatcher также расширяет основной интерфейс Extension , который является лишь интерфейсом маркера. В этом примере мы также реализуем интерфейс AfterAllCallback .

В нашем расширении у нас есть список TestResultStatus , который представляет собой простое перечисление, которое мы собираемся использовать для представления статуса результата теста.

4.1. Обработка результатов теста

Теперь давайте посмотрим, как обработать результаты отдельного метода модульного тестирования:

@Override
public void testDisabled(ExtensionContext context, Optional<String> reason) {
LOG.info("Test Disabled for test {}: with reason :- {}",
context.getDisplayName(),
reason.orElse("No reason"));

testResultsStatus.add(TestResultStatus.DISABLED);
}

@Override
public void testSuccessful(ExtensionContext context) {
LOG.info("Test Successful for test {}: ", context.getDisplayName());

testResultsStatus.add(TestResultStatus.SUCCESSFUL);
}

Начнем с заполнения тела нашего расширения и переопределения методов testDisabled() и testSuccessful() .

В нашем тривиальном примере мы выводим имя теста и добавляем статус теста в список testResultsStatus .

Мы продолжим в том же духе для двух других методов — testAborted() и testFailed() :

@Override
public void testAborted(ExtensionContext context, Throwable cause) {
LOG.info("Test Aborted for test {}: ", context.getDisplayName());

testResultsStatus.add(TestResultStatus.ABORTED);
}

@Override
public void testFailed(ExtensionContext context, Throwable cause) {
LOG.info("Test Failed for test {}: ", context.getDisplayName());

testResultsStatus.add(TestResultStatus.FAILED);
}

4.2. Подведение итогов испытаний

В последней части нашего примера мы переопределим метод afterAll () :

@Override
public void afterAll(ExtensionContext context) throws Exception {
Map<TestResultStatus, Long> summary = testResultsStatus.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

LOG.info("Test result summary for {} {}", context.getDisplayName(), summary.toString());
}

Чтобы быстро напомнить, метод afterAll выполняется после того, как все тестовые методы были запущены. Мы используем этот метод, чтобы сгруппировать различные TestResultStatus , которые у нас есть в списке результатов теста, перед выводом очень простой сводки.

Чтобы получить подробное руководство по обратным вызовам жизненного цикла, ознакомьтесь с нашим превосходным руководством по расширениям JUnit 5 .

5. Запуск тестов

В этом предпоследнем разделе мы увидим, как выглядят результаты наших тестов с использованием нашего простого расширения ведения журнала.

Теперь, когда мы определили наше расширение, мы сначала зарегистрируем его, используя стандартную аннотацию @ExtendWith :

@ExtendWith(TestResultLoggerExtension.class)
class TestWatcherAPIUnitTest {

@Test
void givenFalseIsTrue_whenTestAbortedThenCaptureResult() {
Assumptions.assumeTrue(false);
}

@Disabled
@Test
void givenTrueIsTrue_whenTestDisabledThenCaptureResult() {
Assert.assertTrue(true);
}

//...

Затем мы заполняем наш тестовый класс модульными тестами, добавляя смесь отключенных, прерванных и успешных тестов.

5.1. Просмотр вывода

Когда мы запускаем модульный тест, мы должны увидеть вывод для каждого теста:

INFO  c.b.e.t.TestResultLoggerExtension - 
Test Successful for test givenTrueIsTrue_whenTestAbortedThenCaptureResult()
...
Test result summary for TestWatcherAPIUnitTest {ABORTED=1, SUCCESSFUL=1, DISABLED=2}

Естественно, мы также увидим напечатанную сводку, когда все методы тестирования будут завершены.

6. Гочки

В этом последнем разделе давайте рассмотрим пару тонкостей, о которых следует помнить при работе с интерфейсом TestWatcher :

  • Расширениям TestWatcher не разрешается влиять на выполнение тестов; это означает , что если исключение выдается из TestWatcher , оно не будет распространяться до работающего теста.
  • В настоящее время этот API используется только для отчетов о результатах методов @Test и @TestTemplate.
  • По умолчанию, если для метода testDisabled не указана причина , то он будет содержать полное имя метода тестирования, за которым следует ' is @Disabled '

7. Заключение

Подводя итог, в этом руководстве мы показали, как мы можем использовать JUnit 5 TestWatcher API для обработки результатов выполнения наших тестовых методов.

Полный исходный код примеров можно найти на GitHub .