TDD é a sigla utilizada para Test Driven Development ou em português Desenvolvimento Orientado por Testes. Esta é uma técnica empregada no desenvolvimento de softwares baseado em testes que são escritos antes mesmo do código de produção. Ele se baseia em um ciclo curto de repetições, onde para cada funcionalidade do sistema, um teste é criado antes.

Diferente do que ocorre no modelo Tradicional de Desenvolvimento, onde o passo-a-passo a ser feito é: Requisititos - Design - Codificação - Teste - Implantação. Ou seja, neste modelo o teste para saber se o software irá funcionar só ocorre após a codificação, no final. Mas e se não der certo? Se na hora de mostrar o projeto ao cliente ele apresentar algum erro? Aí acontece aquela famosa frase: Mas na minha máquina funcionou! Neste caso, o desenvolvedor terá que voltar ao início do sistema desenvolvido e alterar requisito, design e código, tudo para faze-lo funcionar novamente.

Como exposto no primeiro parágrafo deste artigo, com o Desenvolvimento Orientado por Testes, os testes serão escritos antes do código de produção e para cada novo destes, haverá um teste. Isto garante mais qualidade no desenvolvimento do código, já que eles deverão ser sempre refatorados. Também assegura mais segurança ao desenvolvedor, com menos chances do software apresentar algum bug ao final do processo.

Assim como em qualquer outra tecnologia, para a prática de TDD leva-se um bom tempo, sendo que o programador deverá ser dedicado e ter vontade de adentrar nesta cultura.  Contudo, através desta prática, desenvolvedores podem aplicar o conceito de melhorar e depurar código, legado desenvolvido a partir de técnicas antigas. No cenário tradicional as tecnologias evoluíram, contudo as pessoas continuam desenvolvendo softwares do mesmo jeito. Existe um certo receio a mudanças e quando mostra-se um novo caminho, diferente do qual as pessoas estão acostumadas a trilhar, é natural que se fique com "um pé atrás". 

Ao começar a desenvolver com TDD é natural que os profissionais achem a prática chata, se estes seguirem a linha de pensamento de que terão que testar primeiro, criar um teste para algo que nem existe, depois escrever o código e assim por diante. Mas após um tempo isto se torna um processo natural e vai se tornando mais fácil. Ao aderir a prática TDD o programador deve ter em mente que ele estará investindo em qualidade, mesmo que para isso seja necessário um certo esforço e muita disciplina.

Benefícios

Muitos programadores desistem de utilizar o TDD por acreditar que perde-se tempo com a prática, já que existem mais códigos a serem desenvolvidos.  De fato, a técnica consiste em realizar um passo de cada vez, o chamado baby steps ou passos de bebê. Se uma lógica é complexa de ser desenvolvida ela é dividida em diversas pequenas partes que evoluem até sua solução final.

No entanto, ao utilizar o TDD o profissional ganha inúmeros benefícios como a elaboração de um código com cada vez mais qualidade, além de possuir mais segurança na correção de bugs. A médio prazo o tempo de desenvolvimento gasto com TDD é menor que o tempo de manutenção corrigindo erros. Você desenvolvedor certamente já deve ter corrigido um bug no sistema, porém criou dois no lugar.

Então, com o TDD obtém-se grau superior de confiança na correção de bugs, visto que qualquer passo que for feito de maneira errônea será mostrado pelos testes. Ganha-se tempo na adição de funcionalidades, já que o sistema é mais flexível e o código limpo. Além disso o uso da técnica gera a possibilidade de Integração Contínua, com builds automáticos e feedbacks rápidos de problemas.

O uso de TDD também garante que o desenvolvedor irá programar cada vez melhor. Mesmo em pouco tempo usando estes testes ele já percebe uma diferença relevante em sua forma de programar. O código desenvolvido por quem utiliza a técnica ficará com cada vez mais qualidade, dando origem a objetos concisos e com menos dependências.

A segurança ao desenvolver é outro fator de relevância. Digamos que, por exemplo, você precise realizar alguma alteração em um software que desenvolveu há algum tempo. Dificilmente irá se lembrar de tudo que merece atenção ao desenvolvimento de um código. O natural é que se faça um trabalho bastante minucioso e cauteloso para a nova implementação em um software que encontra-se em produção. Qualquer alteração feita deverá ser testada prestando atenção nos mínimos detalhes para se ter a garantia que ela não afetará os demais módulos. Este trabalho de forma manual é complicado, pois até então não se sabe ou se lembra ao certo quem afeta o sistema. Ao realizar a técnica do TDD cada passo do programa, por menor que seja, já estará devidamente testado, sendo que qualquer mudança poderá ser feita sem medo.

O que impede a prática?

Além do fator tempo, citado anteriormente, alguns outros motivos fazem com que muitos desenvolvedores desistam de aplicar a prática TDD logo no início. Entre eles está a tendência que os programadores têm de tentar praticar o TDD em código já existente, sendo que este não é o caminho. O código que realizará a lógica do TDD deve ser criado somente após o desenvolvimento do teste e isto é algo de difícil aceitação, pois ainda não se tem nada e já é necessário testar. Além disso, para a prática de TDD leva-se tempo, que irá depender principalmente da disponibilidade e da vontade do programador.

Este não é um processo simples, pois envolve uma mudança de comportamento. A pessoa está acostumada a programar de um jeito e terá que repensar seu modo de fazer e é normal que isso gere receio. Para que o código torne-se mais conciso, tenha menos acoplamentos e dependências o programador deverá forçar seu raciocínio a níveis elevados. O profissional terá que olhar seu código de uma forma jamais vista antes.

Expostos os motivos alegados por muitos desenvolvedores para não usar o TDD e os ganhos de quem é adepto a prática, vamos nos concentrar em como funciona o Desenvolvimento Orientado por Testes.

Leia também:

Ciclo de Desenvolvimento

O ciclo de desenvolvimento do TDD é o seguinte: Red, Green, Refactor, onde;

  • O primeiro passo será escrever um teste que inicialmente não passa (Red)
  • Em segundo lugar adiciona-se uma nova funcionalidade ao sistema
  • Em terceiro lugar, deve-se fazer o teste passar (Green)
  • O código da nova funcionalidade deve ser refatorado, ou seja, o sistema de software deverá ser modificado para melhorar a estrutura interna do código sem alterar seu comportamento externo. (Refactoring)
  • Escreve-se o próximo teste.

Em outras palavras, o novo teste criado inicialmente falha, já que ainda não se tem a implementação da funcionalidade em questão. Em seguida esta funcionalidade é implantada para fazer o teste passar. É necessário que esta funcionalidade recém-criada seja refatorada.

Detalhando cada etapa

1º Criar um teste. O que ocorre é o inverso do modo tradicional de desenvolver: Testamos e Codificamos e não Codificamos e Testamos. De início isto pode parecer estranho, mas há uma lógica para tal passo. O fato de se ter um teste antes que o código é a garantia de que os passos dados a partir dali para a codificação da funcionalidade serão simples, com o objetivo de fazer o teste passar.

2º Teste Falhado. Nesta fase o teste acabou de ser escrito, mas não se tem a implementação. Assim ele certamente falhará, pois ele espera uma resposta que ainda não se tem implementada em lugar algum. Diante disto, o único foco aqui é: fazer o teste passar.

3º Nova Funcionalidade: Aqui o código deve ser escrito da forma mais simples possível. Ele deve ser limpo, simples e funcional, para que ele passe. Aprovado, vamos à próxima fase.

4º Refatoração: É neste momento que você irá analisar melhor aquele código simples, feito apenas para o teste passar. Ele deverá ser refatorado, retirando duplicidade, renomeando variáveis, extraíndo métodos, extraíndo classes e interfaces e utilizando algum padrão conhecido. Esta fase é voltada para você deixar seu código simples, limpo e funcional. Com isso terás um teste que indicará qualquer passo errado que possa ser dado ao tentar melhorar o código.

5º Próximo teste. Inicia-se o processo novamente.

A importância da Refatoração

A refatoração realizada no quarto passo é a melhoria no código, o que já é bom para as práticas tradicionais. Mas com o TDD ela torna-se obrigatória. Isto porque é escrito um teste, uma funcionalidade, porém esta funcionalidade não pode quebrar o outro teste. Se isto acontecer, será necessário um esforço para que o novo código esteja menos acoplado ao código restante. 

Ao fazer isto muda-se a forma de desenvolvimento. Ou seja, ao invés de se projetar a aplicação e tentar escrever um código pensando nas mudanças futuras, já se faz um código teste que guiou a simplicidade do próximo código, que deverá ser refatorado para deixá-lo menos acoplado e com uma maior coesão, fazendo com que este código seja facilmente modificado no futuro, seja para implementação de novas funcionalidades ou correção de problemas.

E é por esse e demais benefícios listados acima que a prática TDD é indicada para quem quer desenvolver com mais segurança e qualidade. Para tanto, o desenvolvedor deverá estar disposto a dedicar um certo tempo e esforço.