Garanta a qualidade do seu código Java com JUnit: Uma visão geral da ferramenta essencial para desenvolvedores
JUnit é uma estrutura de teste de unidade para a linguagem de programação Java. É uma das ferramentas de teste mais populares e amplamente utilizadas para desenvolvimento de software em Java.
O JUnit permite que os desenvolvedores escrevam testes automatizados para suas classes Java. Esses testes podem ser executados automaticamente em um ambiente controlado, para verificar se as classes Java funcionam corretamente em diferentes cenários e situações.
Os testes podem ser organizados em suites de teste, que agrupam testes relacionados. O JUnit também fornece uma série de recursos para verificar o comportamento e o estado de objetos durante a execução do teste, como a comparação de valores, a exceção esperada e a verificação de que os métodos foram chamados.
Por exemplo, se você escreveu um programa que calcula a média de notas, você pode usar o JUnit para testar se ele está calculando corretamente a média para diferentes conjuntos de notas. O JUnit também permite que você verifique se o programa está lidando corretamente com situações inesperadas, como quando as notas não são números válidos.
O JUnit é muito útil porque permite que os programadores detectem e corrijam erros em seus programas antes de liberá-los para uso. Dessa forma, os usuários não precisam lidar com problemas que poderiam ser evitados, e o programa pode ser mais confiável e eficiente.
O JUnit é uma ferramenta de código aberto, distribuída sob a Licença Pública Geral GNU (GPL). É uma das ferramentas mais populares para testes unitários em Java, e é amplamente utilizada em projetos de desenvolvimento de software em todo o mundo.
Configuração
Maven
Para adicionar o JUnit em um projeto Maven, você deve seguir os seguintes passos:
-
Abra o arquivo pom.xml do seu projeto.
-
Adicione a dependência do JUnit no bloco de dependências do Maven, conforme o exemplo abaixo:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Gradle
Para adicionar o JUnit em um projeto Gradle, você deve seguir os seguintes passos:
-
Abra o arquivo build.gradle do seu projeto.
-
Adicione a dependência do JUnit no bloco de dependências do Gradle, conforme o exemplo abaixo:
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.2'
É importante notar que esta versão requer o Java 8 para funcionar.
Arquitetura
A arquitetura do JUnit 5 é composta por vários componentes que trabalham juntos para oferecer uma plataforma de teste de unidade moderna e flexível para a linguagem Java. A arquitetura pode ser dividida em três partes principais: a Plataforma JUnit, o JUnit Jupiter e o JUnit Vintage.
Plataforma JUnit
A Plataforma JUnit é a base da arquitetura do JUnit 5. Ela é responsável por fornecer um ambiente de tempo de execução para a execução dos testes. A Plataforma JUnit é altamente flexível e pode ser integrada com várias ferramentas e frameworks de teste, incluindo Maven, Gradle, Ant e Eclipse. A plataforma é composta por um conjunto de APIs que permitem que as ferramentas de construção executem e relatem os testes.
JUnit Jupiter
O JUnit Jupiter é o novo modelo de programação de teste introduzido no JUnit 5. Ele oferece suporte a recursos avançados de teste, como anotações personalizadas, extensões, testes parametrizados e suporte a diferentes mecanismos de assertivas. O JUnit Jupiter também fornece uma API de extensão flexível que permite que os desenvolvedores estendam o comportamento do JUnit com recursos personalizados.
JUnit Vintage
O JUnit Vintage é responsável por fornecer compatibilidade com versões anteriores do JUnit. Ele permite que os testes escritos usando as versões antigas do JUnit (como JUnit 3 e JUnit 4) sejam executados no novo ambiente de tempo de execução do JUnit 5. O JUnit Vintage também fornece suporte a recursos mais antigos do JUnit, como o uso de asserções de estilo antigo e a execução de testes com o método de nomeação padrão.
Anotações Básicas
@Test
Anotação utilizada para indicar que um método é um teste. Este método deve ser público, sem parâmetros de entrada e sem retorno.
Exemplo:
@Test
void meuTeste() {
// código do teste
}
@BeforeEach
Anotação utilizada para indicar que um método deve ser executado antes de cada teste. Este método pode ser usado para inicializar variáveis ou objetos que serão usados nos testes.
Exemplo:
@BeforeEach
void inicializar() {
// inicialização dos objetos ou variáveis
}
@AfterEach
Anotação utilizada para indicar que um método deve ser executado após cada teste. Este método pode ser usado para limpar objetos ou variáveis que foram usados nos testes.
Exemplo:
@AfterEach
void limpar() {
// limpeza dos objetos ou variáveis
}
@BeforeAll
Anotação utilizada para indicar que um método deve ser executado antes de todos os testes. Este método pode ser usado para inicializar recursos compartilhados entre os testes.
Exemplo:
@BeforeAll
static void inicializarRecursosCompartilhados() {
// inicialização dos recursos compartilhados
}
@AfterAll
Anotação utilizada para indicar que um método deve ser executado após todos os testes. Este método pode ser usado para limpar recursos compartilhados entre os testes.
Exemplo:
@AfterAll
static void limparRecursosCompartilhados() {
// limpeza dos recursos compartilhados
}
@DisplayName
Anotação utilizada para especificar um nome amigável para um teste. O nome fornecido será usado nos relatórios de teste em vez do nome do método de teste. Essa anotação pode ser útil para tornar os nomes dos testes mais legíveis e descritivos.
Exemplo:
@Test
@DisplayName("Teste de soma")
void testarSoma() {
// código do teste
}
@Disabled
Anotação utilizada para desabilitar um teste. Quando essa anotação é usada, o teste não será executado durante a execução do conjunto de testes. Isso pode ser útil quando o teste ainda não está pronto ou não está passando e deve ser trabalhado mais tarde.
Exemplo:
@Test
@Disabled("Teste ainda não implementado")
void testeNaoImplementado() {
// código do teste
}
Afirmações e Suposições
No JUnit 5, você pode realizar afirmações e suposições nos seus testes usando as classes de asserção
e Assertions
.Assumptions
Assertions
As afirmações são usadas para verificar se um valor é igual, maior, menor ou diferente de outro valor esperado. Para realizar afirmações no JUnit 5, você pode usar os métodos estáticos fornecidos pela classe
, tais como:Assertions
-
assertEquals: verifica se dois objetos são iguais.
-
assertNotEquals: verifica se dois objetos não são iguais.
-
assertTrue: verifica se uma condição é verdadeira.
-
assertFalse: verifica se uma condição é falsa.
-
assertNull: verifica se um objeto é nulo.
-
assertNotNull: verifica se um objeto não é nulo.
-
assertThrows: verifica se um método lança uma exceção específica.
Exemplo de como usar a classe
para realizar afirmações no JUnit 5:Assertions
@Test
void testarSoma() {
int resultado = 2 + 2;
Assertions.assertEquals(4, resultado);
}
Assumptions
As suposições são usadas para verificar se uma condição é verdadeira antes de executar um teste. Se a suposição falhar, o teste será interrompido e marcado como "ignorado". Para realizar suposições no JUnit 5, você pode usar os métodos estáticos fornecidos pela classe
, tais como:Assumptions
-
assumeTrue: verifica se uma condição é verdadeira.
-
assumeFalse: verifica se uma condição é falsa.
-
assumeNotNull: verifica se um objeto não é nulo.
Exemplo de como usar a classe
para realizar suposições no JUnit 5:Assumptions
@Test
void testarMultiplicacao() {
boolean isExecutado = Boolean.valueOf(System.getProperty("executado"));
Assumptions.assumeTrue(isExecutado);
int resultado = 2 * 2;
Assertions.assertEquals(4, resultado);
}
Usando asserções e suposições, você pode escrever testes mais robustos e confiáveis que verificam o comportamento do código e asseguram que ele está funcionando corretamente.
Teste de exceção
No JUnit 5, você pode testar erros em seus testes com o método
fornecido pela classe assertThrows
.Assertions
O método
verifica se um método lançou uma exceção específica durante a sua execução. O método aceita dois argumentos: a classe da exceção esperada e uma expressão lambda que contém o código a ser testado.assertThrows
Exemplo de como usar o método
para testar uma exceção no JUnit 5:assertThrows
@Test
void testarDivisaoPorZero() {
assertThrows(ArithmeticException.class, () -> {
int resultado = 10 / 0;
});
}
Neste exemplo, o método
verifica se uma exceção da classe assertThrows
é lançada quando tentamos dividir 10 por 0. Se a exceção não for lançada, o teste falhará.ArithmeticException
Conjuntos de teste
No JUnit 5, você pode configurar um conjunto de testes usando a anotação
e a classe @RunWith
.@SelectClasses
A anotação
é usada para especificar o runner que será usado para executar os testes. No caso do JUnit 5, o runner padrão é o @RunWith
.JUnitPlatform
A classe
é usada para especificar quais classes de teste devem ser executadas como parte da suíte de testes.@SelectClasses
Exemplo de como configurar uma suite de testes no JUnit 5:
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.runner.RunWith;
@RunWith(JUnitPlatform.class)
@SelectClasses({TesteCalculadora.class, TesteMatematica.class})
public class SuiteDeTestes {
// vazio
}
Neste exemplo, a classe
é configurada como uma suite de testes usando a anotação SuiteDeTestes
e a classe @RunWith
. A anotação JUnitPlatform
é usada para especificar as classes de teste que serão executadas como parte da suíte de testes. Neste caso, as classes @SelectClasses
e TesteCalculadora
serão executadas.TesteMatematica
testes dinâmicos
Os testes dinâmicos são uma nova funcionalidade introduzida no JUnit 5 que permitem a criação de testes de forma mais flexível e dinâmica.
Para criar testes dinâmicos no JUnit 5, você deve seguir os seguintes passos:
-
Anote a classe de teste com a anotação
.@TestFactory
-
Crie um método na classe de teste que retorna um objeto do tipo
. Esse método deve conter a lógica para criar os testes dinâmicos e retorná-los como um stream.Stream<DynamicTest>
-
Crie os testes dinâmicos usando o método
. Este método recebe o nome do teste e um objeto Executable que contém a lógica do teste.DynamicTest.dynamicTest()
-
Retorne os testes dinâmicos como um stream usando o método
.Stream.of()
Veja um exemplo de como criar testes dinâmicos no JUnit 5:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.util.stream.Stream;
public class TesteCalculadora {
@TestFactory
public Stream<DynamicTest> testesDeAdicao() {
return Stream.of(
DynamicTest.dynamicTest("Teste 1", () -> assertEquals(4, Calculadora.somar(2, 2))),
DynamicTest.dynamicTest("Teste 2", () -> assertEquals(0, Calculadora.somar(-2, 2))),
DynamicTest.dynamicTest("Teste 3", () -> assertEquals(-4, Calculadora.somar(-2, -2)))
);
}
}
Neste exemplo, a classe
contém um método TesteCalculadora
anotado com a anotação testesDeAdicao()
. Esse método retorna um stream de testes dinâmicos que testam o método @TestFactory
da classe Calculadora.somar()
Cada teste dinâmico é criado usando o método
, que recebe o nome do teste e um objeto DynamicTest.dynamicTest()
contendo a lógica do teste. Os testes são retornados como um stream usando o método Executable
.Stream.of()
Ao executar a classe de teste
, o JUnit 5 executará todos os testes dinâmicos contidos no stream retornado pelo método TesteCalculadora
. Os resultados dos testes serão exibidos na saída padrão do console.testesDeAdicao()
Conclusão
O JUnit é uma ferramenta essencial para garantir a qualidade do código em projetos Java, oferecendo aos desenvolvedores uma estrutura robusta e flexível para criar testes unitários. Com a utilização adequada das anotações e recursos oferecidos pela plataforma, é possível automatizar a execução de testes e verificar se as classes Java estão funcionando corretamente em diferentes cenários e situações. O JUnit 5, em particular, apresenta uma arquitetura moderna e flexível, que oferece suporte a recursos avançados de teste e é compatível com versões anteriores do JUnit. Em suma, o JUnit é uma ferramenta poderosa para garantir a qualidade e confiabilidade do software, além de economizar tempo e recursos de desenvolvimento.