Executando testes JUnit programaticamente, a partir de um aplicativo Java

Executando testes JUnit programaticamente, a partir de um aplicativo Java

1. Visão geral

Neste tutorial, mostraremoshow to run JUnit tests directly from Java code - há cenários em que essa opção é útil.

Se você é novo no JUnit, ou se deseja atualizar para o JUnit 5, pode verificar alguns dosmany tutorials que temos sobre o assunto.

2. Dependências do Maven

Precisaremos de algumas dependências básicas para executar os testes JUnit 4 e JUnit 5:


    
        org.junit.jupiter
        junit-jupiter-engine
        5.2.0
        test
    
    
        org.junit.platform
        junit-platform-launcher
        1.2.0
    


// for JUnit 4

    junit
    junit
    4.12
    test

As versões mais recentes deJUnit 4,JUnit 5 eJUnit Platform Launcher podem ser encontradas no Maven Central.

3. Executando testes JUnit 4

3.1. Cenário de teste

Para JUnit 4 e JUnit 5, vamos configurar algumas classes de teste de "espaço reservado" que serão suficientes para demonstrar nossos exemplos:

public class FirstUnitTest {

    @Test
    public void whenThis_thenThat() {
        assertTrue(true);
    }

    @Test
    public void whenSomething_thenSomething() {
        assertTrue(true);
    }

    @Test
    public void whenSomethingElse_thenSomethingElse() {
        assertTrue(true);
    }
}
public class SecondUnitTest {

    @Test
    public void whenSomething_thenSomething() {
        assertTrue(true);
    }

    @Test
    public void whensomethingElse_thenSomethingElse() {
        assertTrue(true);
    }
}

Ao usar o JUnit 4, criamos classes de teste adicionando a anotação@Test a cada método de teste.

Também podemos adicionar outras anotações úteis, como@Before ou@After, mas isso não está no escopo deste tutorial.

3.2. Executando uma única classe de teste

Para executar testes JUnit a partir do código Java, podemos usar a classeJUnitCore (com uma adição da classeTextListener, usada para exibir a saída emSystem.out):

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(FirstUnitTest.class);

No console, veremos uma mensagem muito simples indicando testes bem-sucedidos:

Running one test class:
..
Time: 0.019
OK (2 tests)

3.3. Executando várias classes de teste

Se quisermosto specify multiple test classes com JUnit 4, podemos usar o mesmo código de uma única classe e simplesmente adicionar as classes adicionais:

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

Result result = junit.run(
  FirstUnitTest.class,
  SecondUnitTest.class);

resultReport(result);

Observe que o resultado é armazenado em uma instância da classeResult de JUnit, que estamos imprimindo usando um método utilitário simples:

public static void resultReport(Result result) {
    System.out.println("Finished. Result: Failures: " +
      result.getFailureCount() + ". Ignored: " +
      result.getIgnoreCount() + ". Tests run: " +
      result.getRunCount() + ". Time: " +
      result.getRunTime() + "ms.");
}

3.4. Executando um Conjunto de Testes

Se precisarmos agrupar algumas classes de teste para executá-las, podemos criar umTestSuite. Esta é apenas uma classe vazia, onde especificamos todas as classes usando as anotações JUnit:

@RunWith(Suite.class)
@Suite.SuiteClasses({
  FirstUnitTest.class,
  SecondUnitTest.class
})
public class MyTestSuite {
}

Para executar esses testes, usaremos novamente o mesmo código de antes:

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(MyTestSuite.class);
resultReport(result);

3.5. Execução de testes repetidos

Um dos recursos interessantes do JUnit é que podemosrepeat tests by creating instances of RepeatedTest. Isso pode ser muito útil quando estamos testando valores aleatórios ou para verificações de desempenho.

No próximo exemplo, vamos executar os testes deMergeListsTest cinco vezes:

Test test = new JUnit4TestAdapter(FirstUnitTest.class);
RepeatedTest repeatedTest = new RepeatedTest(test, 5);

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

junit.run(repeatedTest);

Aqui, estamos usandoJUnit4TestAdapter como um wrapper para nossa classe de teste.

Podemos até criar suítes programaticamente, aplicando testes repetidos:

TestSuite mySuite = new ActiveTestSuite();

JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));

mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(FirstUnitTest.class), 5));
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(SecondUnitTest.class), 3));

junit.run(mySuite);

4. Executando testes JUnit 5

4.1. Cenário de teste

Com JUnit 5, usaremos as mesmas classes de teste de amostra da demo anterior -FirstUnitTesteSecondUnitTest, com algumas pequenas diferenças devido a uma versão diferente do framework JUnit, como o pacote para@Teste métodos de asserção.

4.2. Executando uma única classe de teste

Para executar testes JUnit 5 do código Java, vamos configurar uma instância deLauncherDiscoveryRequest. Ele usa uma classe construtora na qual devemos definir seletores de pacotes e testar filtros de nome de classe, para obter todas as classes de teste que queremos executar.

Essa solicitação é então associada a um iniciador e, antes de executar os testes, também configuraremos um plano de teste e um ouvinte de execução.

Ambos oferecerão informações sobre os testes a serem executados e os resultados:

public class RunJUnit5TestsFromJava {
    SummaryGeneratingListener listener = new SummaryGeneratingListener();

    public void runOne() {
        LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
          .selectors(selectClass(FirstUnitTest.class))
          .build();
        Launcher launcher = LauncherFactory.create();
        TestPlan testPlan = launcher.discover(request);
        launcher.registerTestExecutionListeners(listener);
        launcher.execute(request);
    }
    // main method...
}

4.3. Executando várias classes de teste

Podemos definir seletores e filtros para a solicitação para executar várias classes de teste.

Vamos ver como podemos definir seletores de pacote e filtros de nome de classe de teste, para obter todas as classes de teste que desejamos executar:

public void runAll() {
    LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
      .selectors(selectPackage("com.example.junit5.runfromjava"))
      .filters(includeClassNamePatterns(".*Test"))
      .build();
    Launcher launcher = LauncherFactory.create();
    TestPlan testPlan = launcher.discover(request);
    launcher.registerTestExecutionListeners(listener);
    launcher.execute(request);
}

4.4. Saída de teste

No métodomain(), chamamos nossa classe e também usamos o ouvinte para obter os detalhes do resultado. Desta vez, o resultado é armazenado comoTestExecutionSummary.

A maneira mais simples de extrair suas informações é simplesmente imprimindo em um fluxo de saída do console:

public static void main(String[] args) {
    RunJUnit5TestsFromJava runner = new RunJUnit5TestsFromJava();
    runner.runAll();

    TestExecutionSummary summary = runner.listener.getSummary();
    summary.printTo(new PrintWriter(System.out));
}

Isso nos dará os detalhes de nossa execução de teste:

Test run finished after 177 ms
[         7 containers found      ]
[         0 containers skipped    ]
[         7 containers started    ]
[         0 containers aborted    ]
[         7 containers successful ]
[         0 containers failed     ]
[        10 tests found           ]
[         0 tests skipped         ]
[        10 tests started         ]
[         0 tests aborted         ]
[        10 tests successful      ]
[         0 tests failed          ]

5. Conclusão

Neste artigo, mostramos como executar testes JUnit programaticamente a partir do código Java, cobrindo o JUnit 4, bem como a versão recente do JUnit 5 desta estrutura de teste

Como sempre, a implementação dos exemplos mostrados aqui está disponível no GitHub paraJUnit 5 examples, bem comoJUnit 4.