Curso JUnit: #3 - Evoluindo nossos testes com o JUnit
Depois de ter entendido o que são testes, qual a sua importância para o desenvolvimento de softwares e depois de criar seu primeiro teste com o JUnit, vamos evoluir em nossa jornada e cobrir mais cenários de testes para garantir que nossa classe funciona corretamente.
Se analisarmos novamente nossas regras de negócio veremos que duas delas dizem:
"Não deve ser possível gerar uma senha com menos de 4 digitos"
"Não deve ser possível gerar uma senha com mais de 100 digitos"
Porém, nosso código como está hoje permite que sejam geradas senhas de qualquer tamanho, inclusive com 0 dígitos. Precisamos então corrigir isso.
public String gerarSenhaNumerica(int tamanho) throws Exception {
if (tamanho < 4 || tamanho > 100) {
throw new Exception("Só é possível gerar senhas com comprimento entre 4 e 100 digitos");
}
String senha = "";
Random random = new Random();
int MAIOR_VALOR_POSSIVEL = 9;
for (int i = 0; i < tamanho; i++) {
int numeroAleatorio = random.nextInt(MAIOR_VALOR_POSSIVEL + 1);
senha = senha.concat(String.valueOf(numeroAleatorio));
}
return senha;
}
Perceba que agora implementamos um bloco de código que garante o tamanho informado deve ser maior ou igual a 4 e menor ou igual a 100.
Com isso, precisamos agora atualizar nosso arquivo de teste informando que esse método pode gerar uma Exception.
@Test
@DisplayName("Deve ser possível gerar uma senha numérica com 8 digitos")
public void testGerarSenhaNumericaComOitoDigitos() throws Exception {
// ...
}
O código continua funcionando corretamente, e o teste passa sem nenhum problema, porém precisamos escrever novos testes para garantir que essas novas regras de negócio foram satisfeitas.
@Test
@DisplayName("Deve lançar uma Exception ao tentar gerar uma senha numérica com tamanho inválido")
public void testLancarUmaExceptionQuandoTamanhoMenorQueQuatro() throws Exception {
// Arrange
int tamanho = 2;
GeradorDeSenhas geradorDeSenhas = new GeradorDeSenhas();
// Act
Executable executable = () -> geradorDeSenhas.gerarSenhaNumerica(tamanho);
// Assert
Assertions.assertThrows(Exception.class, executable);
}
Prontinho, agora temos um teste que garante que ao informar um valor inválido o método lançará uma Exception, mas... Será que de fato eu tenho essa garantia com esse código? E se informar 3 será que vai lançar essa Exception? E se eu informar 150 será que lançará essa Exception?
Um valor fixo desse não será o suficiente para termos essa garantia, logo, precisaríamos escrever vários testes para cobrir esses cenários, o que se tornaria impraticável. Pensando nisso o JUnit trouxe uma annotation bem interessante para resolver esse "problema".
Vamos modificar um pouco o nosso teste
@ParameterizedTest
@ValueSource(ints = { -1, 0, 1, 2, 3, 101, 150, 1000 })
@DisplayName("Deve lançar uma Exception ao tentar gerar uma senha numérica com tamanho inválido")
public void testLancarUmaExceptionQuandoTamanhoInvalido(int tamanho) throws Exception {
// Arrange
GeradorDeSenhas geradorDeSenhas = new GeradorDeSenhas();
// Act
Executable executable = () -> geradorDeSenhas.gerarSenhaNumerica(tamanho);
// Assert
Assertions.assertThrows(Exception.class, executable);
}
Aproveitei e mudei também o DisplayName e o nome do método para fazer mais sentido com o novo cenário.
Ao executar esse teste o resultado será:
Ou seja, ao invés de executar o método apenas uma vez, esse método será executado 8 vezes, com 8 valores diferentes.
Vamos agora entender cada parte das alterações realizadas
@ParameterizedTest
@ValueSource(ints = { -1, 0, 1, 2, 3, 101, 150, 1000 })
@DisplayName("Deve lançar uma Exception ao tentar gerar uma senha numérica com tamanho inválido")
A annotation @Test
foi substituída pela annotation @ParameterizedTest
. Isso indica ao JUnit que o parâmetro que será informado no método a seguir receberá cada um dos valores da lista informada em @ValueSource
.
public void testLancarUmaExceptionQuandoTamanhoInvalido(int tamanho) throws Exception { }
O método que não recebia nenhum parâmetro agora recebe um parâmetro inteiro conforme explicado acima
E por fim, a variável tamanho, presente no corpo do método, foi removida.
int tamanho = 8;
Vamos agora propositalmente gerar um erro para vermos como o JUnit se comporta.
Abra a sua classe GeradorDeSenhas, remova temporariamente o bloco abaixo
if (tamanho < 4 || tamanho > 100) {
throw new Exception("Só é possível gerar senhas com comprimento entre 4 e 100 digitos");
}
Ao executar nosso teste a saída será um pouco diferente agora
Perceba que o nosso primeiro método de teste continua funcionando, mas o segundo método parou de funcionar. Ou seja, com testes unitário você se sente mais seguro para refatorar seu código, visto que se você mexer em algo que não deveria, o teste vai quebrar. 🙂
No próximo post vamos evoluir mais nossa camada de testes e conhecer mais alguns detalhes do JUnit, espero vocês lá.