Ferramentas

JUnit

Testes Unitários

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.

img

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

  1. Red: O teste foi feito para falhar
  2. Green: O teste precisa passar com o mínimo de recurso
  3. 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.
🏆 Sucesso
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.

img

🔔 Atenção
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.

  1. Criando um projeto maven com IntelliJ

img

ℹ️ Informação
O nome do projeto, diretório, versão do Java, GroupId e ArtifactId são à sua escolha
  1. Adicionando a dependência do JUnit 5 no pom.xml

img

<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:

  1. 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;
🏆 Sucesso
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.

img

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.

img

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.

img

📌 Para fixar
É 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.

img

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;
}
🚨 Alerta
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

img

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:

🔔 Atenção
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:

  1. Ter uma base de testes espelho de produção
  2. Ter uma base de testes somente com a estrutura de produção
  3. Usar um banco de dados em memória como: SQLite, H2 Database ou HSQLDB (mais recomendado)

Referências