JUnit
TDD
Fazer um código funcionar de primeira é o mesmo que torcer para acertar na loteria, brincadeiras à parte, devemos entender que o que conta, é a consistência do seu algorítimo e não quantas vezes foram necessárias refatorar.
Diante desta reflexão, vamos conhecer o TDD Test Driven Development ou em português Desenvolvimento guiado por testes que é uma técnica de desenvolvimento de software que se relaciona com o conceito de verificação e validação e se baseia em um ciclo curto de repetições.
Ciclo de desenvolvimento
- Red: O teste foi feito para falhar
- Green: O teste precisa passar com o mínimo de recurso
- Refactor: Implementar o que foi especificado na documentação.
Motivações
Quais são os fatores motivacionais que levam um projeto a adotar o TDD como metodologia para qualidade do software?
- Segurança para realizar modificações no código e rápido feedback em problemas durante refatorações;
- Menos bugs no produto, ocasionando em um menor tempo de depuração e correção, liberando o foco do time de desenvolvimento;
- Correção mais completa dos bugs encontrados;
- Código mais simples e melhor escrito;
- Viabilização de uma documentação atualizada sobre cada parte do sistema;
- Reforço à cultura da qualidade.
Antes de prosseguirmos para a parte prática não esqueça, a qualidade do seu software dependerá mais da sua compreensão das regras de negócio do que o nível de cobertura dos testes implementados.
JUnit
O JUnit é um framework open-source, que se assemelha ao raio de testes software java, criado por Erich Gamma e Kent Beck, com suporte à criação de testes automatizados na linguagem de programação Java. Esse framework facilita a criação e manutenção do código para a automação de testes com apresentação dos resultados.
Toda a abordagem que será apresentada segue as definições da versão 5 do JUnit, considere algumas mudanças diante das versões anteriores.
Projeto Maven
Considerando o projeto maven (sem SpringBoot), vamos adicionar a dependência do JUnit 5 para iniciarmos o nosso desenvolvimento baseado nas diretrizes do TDD.
- Criando um projeto maven com IntelliJ
O nome do projeto, diretório, versão do Java, GroupId e ArtifactId são à sua escolha
- Adicionando a dependência do JUnit 5 no
pom.xml
<dependencies>
...
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
...
</dependencies>
O que testar ?
Você agora deve estar perguntando. O que eu devo testar? Por onde começar? Como confirmar se eu estou aplicando TDD em meu projeto?
Bem, diante destas três ou demais perguntas realizaremos os procedimentos conforme sugeridos abaixo:
- Definir um contexto ou regra de negócio:
Vamos utilizar um dos inúmeros requisitos apresentado no tópico A Proposta em nossa plataforma.
O requisito trata-se da necessidade de garantir que um determinado texto seja ajustado considerando as regras abaixo:
- O texto deverá ter no máximo 30 caracteres;
- Se o texto tiver a quantidade máxima de caracteres inferior a 30, deve-se ser complementado com espaços a direita;
Sabemos que Java é baseado em classes, logo, devemos pensar em uma classe que assumisse este papel de ajustar textos, que tal
TextoUtils
?Etapa Red
Abaixo conseguimos visualizar a implementação inicial onde percebemos que houve falha em nosso teste, pois o comprimento da variável texto
é superior a 30.
Etapa Green
Precisamos agora garantir que o nosso teste obtenha sucesso nas próximas execuções, porém, ainda sem aplicar toda a lógica e algorítimos necessários.
Começamos com a criação da classe que terá o papel de ajustar texto na nossa aplicação.
public class TextoUtil {
//este método é static para não precisar criar um objeto de TextoUtil
public static String ajustar(String textoAtual){
//subtring -> retorna uma parte do texto considerando os parametro inicio e fim
String textoAjustado = textoAtual.substring(0,30);
return textoAjustado;
}
}
Usaremos o método da classe TextoUtil para garantir se agora o nosso teste será bem-sucedido.
Etapa Refactor
Quem nunca ouviu aquela frase Alegria de pobre dura pouco, pois é, precisaremos a partir de agora entrar em loop
de implementação, execução e testes da funcionalidade que acabamos de validar.
É na etapa de Refactor que teremos a oportunidade de revisar os requisitos do projetos e até mesmo identificar ausência, divergências e possíveis falhas na especificação.
Como esperado gostaríamos que o mesmo método ajustar
também pudesse atender ao requisito apresentado anteriormente de preencher com espaços à direita quando o texto for inferior a 30.
Vamos aproveitar este cenário para apresentar duas abordagens e comprovar o quanto é importante conhecer e dominar os recursos da linguagem refatorando o método ajustar
da classe TextoUtil
.
public static String ajustar(String textoAtual){
String textoAjustado = "";
if(textoAtual.length()>=30)
textoAjustado = textoAtual.substring(0,30);
else
textoAjustado = String.format("%-30s", textoAtual);
return textoAjustado;
}
Quase íamos nos esquecendo, e se nossa função
ajustar
por alguma razão lançar uma exceção?
Imagina querermos ajustar um texto definido como null
? Que catástrofe que seria em 😳.public static String ajustar(String textoAtual){
if(textoAtual==null)
throw new IllegalArgumentException("O texto informado não pode ser nulo");
return String.format("%-30.30s", textoAtual);
}
Prontinho mais um teste adicionado em nosso software.
@Test
public void textoNullOrIllegalTest(){
String texto = null;
Exception exception = Assertions.assertThrows(IllegalArgumentException.class, () -> {
TextoUtil.ajustar(texto);
});
String expectedMessage = "O texto informado não pode ser nulo";
String actualMessage = exception.getMessage();
//valida se a mensagem apresentada é igual a esperada
Assertions.assertTrue(actualMessage.equals(expectedMessage));
//valida se a instância da exceção é do tipo esperado
Assertions.assertInstanceOf(IllegalArgumentException.class, exception);
}
Mocks
Objetos mock, objetos simulados ou simplesmente mock em desenvolvimento de software são objetos que simulam o comportamento de objetos reais de forma controlada. São normalmente criados para testar o comportamento de outros objetos
Para a linguagem Java podemos adicionar a biloteca Mockito para auxiliar nos projetos que adotam TDD, abaixo iremos listar algumas referências de conteúdos:
Não iremos explorar tanto os conceitos e recursos de testes baseados a Mock por acreditarmos que pode inferir na qualidade dos testes.
Persistência
Grande parte de nossos testes envolvem a manipulação de registros em um banco de dados, mas sabemos que nunca, jamais e de forma alguma devemos ter acesso aos dados reais de seu software. Então, como garantir a qualidade de nosso sistema no que se refere a manipulação de tais registros? Um ambiente de desenvolvimento pode adotar como estratégia de solução as seguintes alternativas abaixo:
- Ter uma base de testes espelho de produção
- Ter uma base de testes somente com a estrutura de produção
- Usar um banco de dados em memória como: SQLite, H2 Database ou HSQLDB (mais recomendado)