API TestWatcher do JUnit 5
1. Visão geral
Durante o teste de unidade, podemos periodicamente desejar processar os resultados de nossas execuções de método de teste. Neste tutorial rápido,we’ll take a look at how we can accomplish this using the TestWatcher API provided by JUnit.
Para obter um guia detalhado de testes com JUnit, verifique nosso excelenteGuide to JUnit 5.
2. A APITestWatcher
In short, the TestWatcher interface defines the API for extensions that wish to process test results. Uma maneira de pensar nessa API é fornecer ganchos para obter o status de um caso de teste individual.
Mas, antes de mergulharmos em alguns exemplos reais,let’s take a step back and briefly summarize the methods in the TestWatcher interface:
-
testAborted(ExtensionContext context, Throwable cause)
Para processar os resultados de um teste abortado, podemos substituir o métodotestAborted. Como o nome sugere, esse método é chamado após a interrupção de um teste.
-
testDisabled(ExtensionContext context, Optional reason)
Podemos substituir o métodotestDisabled quando quisermos lidar com os resultados de um método de teste desabilitado. Este método também pode incluir o motivo pelo qual o teste está desativado.
-
testFailed(ExtensionContext context, Throwable cause)
Se quisermos fazer algum processamento adicional após uma falha de teste, podemos simplesmente implementar a funcionalidade no métodotestFailed. Este método pode incluir a causa da falha no teste.
-
testSuccessful(ExtensionContext context)
Por último, mas não menos importante, quando desejamos processar os resultados de um teste bem-sucedido, simplesmente substituímos o métodotestSuccessful.
Devemos notar que todos os métodos contêmExtensionContext. Isso encapsula o contexto em que o teste atual foi executado.
3. Dependências do Maven
Primeiro, vamos adicionar as dependências do projeto que precisaremos para nossos exemplos. Além da biblioteca principal JUnit 5junit-jupiter-engine, também precisaremos da bibliotecajunit-jupiter-api:
org.junit.jupiter
junit-jupiter-api
5.4.2
test
Como sempre, podemos obter a versão mais recente deMaven Central.
4. Exemplo de ATestResultLoggerExtension
Agora que temos um conhecimento básico da APITestWatcher, veremos um exemplo prático.
Let’s begin by creating a simple extension for logging the results and providing a summary of our tests. Nesse caso, para criar a extensão, precisamos definir uma classe que implemente a interfaceTestWatcher:
public class TestResultLoggerExtension implements TestWatcher, AfterAllCallback {
private List testResultsStatus = new ArrayList<>();
private enum TestResultStatus {
SUCCESSFUL, ABORTED, FAILED, DISABLED;
}
//...
}
As with all extension interfaces, the TestWatcher interface also extends the main Extension interface, que é apenas uma interface de marcador. Neste exemplo, também implementamos a interfaceAfterAllCallback.
Em nossa extensão, temos uma lista deTestResultStatus, que é uma enumeração simples que usaremos para representar o status de um resultado de teste.
4.1. Processando os resultados do teste
Agora, vamos ver como processar os resultados do método de teste de unidade individual:
@Override
public void testDisabled(ExtensionContext context, Optional 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);
}
Começamos preenchendo o corpo de nossa extensão eoverriding the testDisabled() and testSuccessful() methods.
Em nosso exemplo trivial, geramos o nome do teste e adicionamos o status do teste à listatestResultsStatus.
Continuaremos desta forma para os outros dois métodos -testAborted()etestFailed():
@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 Aborted for test {}: ", context.getDisplayName());
testResultsStatus.add(TestResultStatus.FAILED);
}
4.2. Resumindo os resultados do teste
Na última parte do nosso exemplo,we’ll override the afterAll() method:
@Override
public void afterAll(ExtensionContext context) throws Exception {
Map summary = testResultsStatus.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
LOG.info("Test result summary for {} {}", context.getDisplayName(), summary.toString());
}
Para recapitular rapidamente, o métodoafterAll é executado após todos os métodos de teste terem sido executados. Usamos este método para agrupar os diferentesTestResultStatus que temos na lista de resultados de teste antes de produzir um resumo muito básico.
Para obter um guia detalhado de Callbacks do Ciclo de Vida, verifique nosso excelenteGuide to JUnit 5 extensions.
5. Executando os testes
Nesta penúltima seção, veremos como fica a saída de nossos testes usando nossa extensão de registro simples.
Agora que definimos nossa extensão, vamos primeiro registrá-la usando a anotação padrão@ExtendWith:
@ExtendWith(TestResultLoggerExtension.class)
class TestWatcherAPIUnitTest {
@Test
void givenFalseIsTrue_whenTestAbortedThenCaptureResult() {
Assumptions.assumeTrue(false);
}
@Disabled
@Test
void givenTrueIsTrue_whenTestDisabledThenCaptureResult() {
Assert.assertTrue(true);
}
//...
Em seguida, preenchemos nossa classe de teste com testes de unidade, adicionando uma mistura de testes desabilitados, abortados e bem-sucedidos.
5.1. Revisando o resultado
Quando executamos o teste de unidade, devemos ver a saída de cada teste:
INFO c.b.e.t.TestResultLoggerExtension -
Test Successful for test givenTrueIsTrue_whenTestAbortedThenCaptureResult()
...
Test result summary for TestWatcherAPIUnitTest {ABORTED=1, SUCCESSFUL=1, DISABLED=2}
Naturalmente, também veremos o resumo impresso quando todos os métodos de teste forem concluídos.
6. Pegadinhas
Nesta última seção, vamos revisar algumas das sutilezas que devemos conhecer ao trabalhar com a interfaceTestWatcher:
-
As extensões do TestWatcher não têm permissão para influenciar a execução dos testes; isso significaif an exception is thrown from a TestWatcher, it will not be propagated up to the running test
-
Atualmente, esta API é usada apenas para relatar os resultados dos métodos@Test e métodos@TestTemplate
-
Por padrão, se nenhum motivo for fornecido para o métodotestDisabled, ele conterá o nome totalmente qualificado do método de teste seguido por 'is @Disabled'
7. Conclusão
Para resumir, neste tutorial, mostramos como podemos fazer uso da API JUnit 5TestWatcher para processar os resultados de nossas execuções de método de teste.
O código-fonte completo dos exemplos pode ser encontradoover on GitHub.