Entendendo e aplicando o Test Driven Development (TDD) - Blog One Day Testing - Powered by Sofist
Atualmente o desenvolvimento de software e escrita de códigos contam com muitos recursos e tecnologias que visam padronizar as atividades e facilitar o dia a dia dos profissionais. Alguns desses padrões e metodologias são focados em aumentar a qualidade do software, e uma dessas metodologias é o Test Driven Development (TDD) – que é o desenvolvimento orientado a testes.
Nesse artigo vou explicar o que é o TDD, quais são seus benefícios e demonstrar um exemplo prático de seu funcionamento.
A definição do Test Driven Development (TDD)
No TDD basicamente são criados testes antes do código de cada funcionalidade. Isso funciona em ciclos, onde inicialmente escrevemos o teste e o executamos com o objetivo de que ele falhe. Após isso, criamos o código de nossa funcionalidade e rodamos novamente o teste, que por sua vez irá passar.
Com o teste passando inicia-se o processo de refatoração, onde o código é melhorado, ajustado e otimizado. A partir desse momento o teste deve sempre passar para garantir que nada do que foi planejado para essa funcionalidade foi quebrado. Esse processo é comumente conhecido como "Red, Green, Refactor", conforme demonstra a imagem abaixo.
Usando essa metodologia, a pessoa desenvolvedora tem muito mais segurança ao realizar alterações no código e também obtém um feedback rápido caso algo não saia como o esperado em uma refatoração. As correções de bugs também são mais completas, pois, em muitos casos, tanto o código quanto o teste serão corrigidos dando uma maturidade muito maior ao código do projeto.
A diminuição de tempo com depuração de código também é um benefício, já que são gerados menos bugs no código devido a escrita antecipada de testes. Também podemos pontuar que o código tende a ficar melhor escrito em pequenos blocos e com uma escrita mais simples devido a característica da escrita de testes, facilitando seu entendimento.
Quando se fala em TDD, muito se comenta sobre o tempo alto a ser investido pela necessidade da escrita dos testes, mas isso se prova como sendo um mito. Aplicar essa metodologia acaba gerando uma economia de tempo, uma vez que a incidência de bugs no produto será menor, diminuindo o tempo necessário para correção de problemas encontrados ao longo do processo de desenvolvimento.
Já comentamos aqui no blog que o tempo médio gasto semanalmente por desenvolvedores para corrigir problemas de software é 17 horas. Imagine só o quanto o TDD pode ajudar seu time a redirecionar tempo e esforço para tarefas que geram mais valor aos usuários.
A cobertura de testes unitários também é impactado, uma vez que ela se torna muito mais simplificada e fácil de manter, pois como os testes são criados antes mesmo das funcionalidades, o código sempre estará coberto por pelo menos um teste em cada nova funcionalidade implementada.
Quer saber mais sobre testes unitários? Leia nosso artigo sobre a Pirâmide de Testes.
Com o uso dessa metodologia, a cultura de qualidade dentro dos times é reforçada desde o início da escrita de código, além de também ficar aderente ao shift left testing, onde levamos a etapa de testes cada vez mais para o início do ciclo de vida do desenvolvimento de software.
Quantos benefícios, não? Vamos relembrá-los logo abaixo antes de ir para o exemplo prático:
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 e às práticas de shift-left.
Entrando em um exemplo prático, vamos criar um sistema simples de uma calculadora usando Java e JUnit, onde iremos escrever os testes, depois implementar a funcionalidade e após isso refatorar.
Inicialmente teremos a classe de testes onde criaremos nosso primeiro teste para a operação de soma de dois números inteiros; Criamos esse teste antes mesmo de ter criado a classe Calculadora e o método da operação de soma.
Ao executar essa classe de teste visualizamos o erro, pois nem mesmo a classe existe. Consequentemente, o método da operação de soma também não.
Agora implementamos a classe Calculadora e criamos o método com a operação de soma de dois números inteiros.
Rodamos novamente nossa classe de teste e a partir desse ponto o teste da operação soma começa a passar com sucesso.
A partir desse ponto o ciclo se inicia novamente, onde iremos criar um novo teste para uma nova operação, que seria a subtração de dois números inteiros.
Rodamos nossos testes novamente e a classe de testes falha, pois o método da operação de subtração não está implementado ainda em nossa classe Calculadora.
Vamos então à classe calculadora e refatoramos o código, adicionando o método de subtração de dois números inteiros logo após nosso método de soma.
Rodamos novamente a classe de testes e agora os dois testes estão passando com sucesso, garantindo que nosso novo código não gerou bugs e está atendendo corretamente as funcionalidades.
Nesse exemplo podemos ver um passo a passo bem simples, porém objetivo, demonstrando como funciona o TDD na prática e como os conceitos são aplicados no código de teste e das funcionalidades.