Test-driven development (TDD) ou em português desenvolvimento guiado por testes é 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: Primeiramente o desenvolvedor escreve um caso de teste automatizado que define uma melhoria desejada ou uma nova funcionalidade. Então, é produzido código que possa ser validado pelo teste para posteriormente o código ser refatorado para um código sob padrões aceitáveis. Kent Beck, considerado o criador ou o 'descobridor' da técnica, declarou em 2003 que TDD encoraja designs de código simples e inspira confiança.Beck, K. Test-Driven Development by Example, Addison Wesley - Vaseem, 2003 Desenvolvimento dirigido por testes é relacionado a conceitos de programação de Extreme Programming, iniciado em 1999, "Extreme Programming", Computerworld (online), December 2001, webpage: Computerworld-appdev-92. mas recentemente tem-se criado maior interesse pela mesma em função de seus próprios ideais.Newkirk, JW and Vorontsov, AA. Test-Driven Development in Microsoft .NET, Microsoft Press, 2004. Através de TDD, programadores podem aplicar o conceito de melhorar e depurar código legado desenvolvido a partir de técnicas antigas.Feathers, M. Working Effectively with Legacy Code, Prentice Hall, 2004

miniaturadaimagem|TDD aplicado ao desenvolvimento de um algoritmo em JavaScript que transforma números romanos em números ordinários

Requisitos Desenvolvimento dirigido por testes requer dos desenvolvedores criar testes automatizados que definam requisitos em código antes de escrever o código da aplicação. Os testes contém asserções que podem ser verdadeiras ou falsas. Após as mesmas serem consideradas verdadeiras após sua execução, os testes confirmam o comportamento correto, permitindo os desenvolvedores evoluir e refatorar o código. Normalmente todos os testes são efetuados de forma continua de acordo com o desenvolvimento cada funcionalidade criada deve ser acompanhada de um teste bem descrito e projetado, então deve-se escolher a área do projeto ou requisitos da tarefa para melhor orientar o desenvolvimento destes testes.

Desenvolvedores normalmente usam frameworks de testes, como xUnit, para criar e executar automaticamente uma série de casos de teste.

Evolução histórica Kent Beck, considerado o criador ou o descobridor da técnica, declarou em 2003 que TDD encoraja designs de código simples e inspira confiança. Desenvolvimento dirigido por testes é relacionado a conceitos de programação de Extreme Programming, iniciado em O desenvolvimento guiado por testes, em língua inglesa Test Driven Development (TDD), teve origem na metodologia ágil criado por Kent Beck. Ela se tornou mais conhecida entre desenvolvedores após a publicação do livro TDD by exemplo de Kent Beck em 2002. Ainda que utilização já ocorresse há algumas décadas, segundo Larman e Basili (2003), o manifesto ágil contribuiu muito para impulsioná-la. próprios ideais. Através de TDD, programadores podem aplicar o conceito de melhorar e depurar código legado desenvolvido a partir de técnicas antigas.

Ciclo de desenvolvimento

1. Adicione um teste Para escrever um teste, o desenvolvedor precisa claramente entender as especificações e requisitos da funcionalidade. O desenvolvedor pode fazer isso através de caso de uso que cubram os requisitos e exceções condicionais.

Esta é a diferenciação entre desenvolvimento dirigido a testes entre escrever testes de unidade depois do código desenvolvido. Ele torna o desenvolvedor focado nos requisitos antes do código, que é uma sutil porem importante diferença.

Em um estudo por George e Willians (2003), com programadores constatou-se que: (87,5%) acreditavam que TDD facilita uma melhor abordagem e compreensão dos requisitos; 95,8% acreditavam que o tempo de depuração foi reduzido; 78% acreditavam que a produtividade do time aumentou; 92% acreditavam que melhorou a qualidade do código; 79% acreditavam que o design ficou mais simples; e no total 71% acreditavam que a abordagem foi eficaz.

2. Execute todos os testes e veja se algum deles falha Esse passo valida se todos os testes estão funcionando corretamente e se o novo teste não traz nenhum equívoco, sem requerer nenhum código novo. Pode-se considerar que este passo então testa o próprio teste: ele regula a possibilidade de novo teste passar.

O novo teste deve então falhar pela razão esperada: a funcionalidade não foi desenvolvida. Isto aumenta a confiança (por outro lado não exatamente a garante) que se está testando a coisa certa, e que o teste somente irá passar nos casos intencionados.

3. Escrever código O próximo passo é escrever código que irá ocasionar ao teste passar. O novo código escrito até esse ponto poderá não ser perfeito e pode, por exemplo, passar no teste de uma forma não elegante. Isso é aceitável porque posteriormente ele será melhorado.

O importante é que o código escrito deve ser construído somente para passar no teste; nenhuma funcionalidade (muito menos não testada) deve ser predita ou permitida em qualquer ponto.

4. Execute os testes automatizados e veja-os executarem com sucesso Se todos os testes passam agora, o programador pode ficar confiante de que o código possui todos os requisitos testados. Este é um bom ponto que inicia o passo final do ciclo TDD.

5. Refatorar código Nesse ponto o código pode ser limpo como necessário. Ao reexecutar os testes, o desenvolvedor pode confiar que a refatoração não é um processo danoso a qualquer funcionalidade existente. Um conceito relevante nesse momento é o de remoção de duplicação de código, considerado um importante aspecto ao design de um software. Nesse caso, entretanto, isso aplica remover qualquer duplicação entre código de teste e código de produção — por exemplo magic numbers or strings que nós repetimos nos testes e no código de produção, de forma que faça o teste passar no passo 3.

6. Repita tudo Iniciando com outro teste, o ciclo é então repetido, empurrando a funcionalidade a frente. O tamanho dos passos deve ser pequeno - tão quanto de 1 a 10 edições de texto entre cada execução de testes. Se novo código não satisfaz rapidamente um novo teste, ou outros testes falham inesperadamente, o programador deve desfazer ou reverter as alterações ao invés do uso de excessiva depuração. A integração contínua ajuda a prover pontos reversíveis. É importante lembrar que ao usar bibliotecas externas não é interessante gerar incrementos tão pequenos que possam efetivamente testar a biblioteca , a menos que haja alguma razão para acreditar que a biblioteca tenha defeitos ou não seja suficientemente completada com suas funcionalidades de forma a servir às necessidades do programa em que está sendo escrito.

Estilos de desenvolvimento Há vários aspectos ao usar desenvolvimento dirigido a testes, por exemplo os princípios "Keep It Simple, Stupid" (KISS) e "You Ain`t Gonna Need It" (YAGNI). Focando em escrever código somente para os testes passarem, o design do sistema pode ser mais limpo e claro do que o que é alcançado por outros métodos. Em Test-Driven Developmente By Example Kent Beck sugere o princípio "Fake it, till you make it". Para alcançar altos níveis conceituais de design (como o uso de Design Pattern), testes são escritos de forma que possam gerar o design. O código pode acabar permanecendo mais simples do que o padrão alvo, entretanto ele deve passar em todos os testes requeridos. Isto pode ser inaceitável de primeira mas ele permite o desenvolvedor focar somente no que é importante.

Falhar primeiro os casos de testes. A ideia é garantir que o teste realmente funciona e consegue capturar um erro. Assim que ele é mostrado, a funcionalidade almejada pode ser implementada. Isto tem sido apontado como o "Test-Driven Mantra", conhecido como vermelho/verde/refatorar onde vermelho significa falhar onde pelo menos uma asserção falha ,e verde é passar, que significa que todas as asserções foram verdadeiras.

Desenvolvimento dirigido a testes constantemente repete os passos de adicionar casos de teste que falham, passando e refatorando-os. Ao receber o resultado esperado em cada estágio reforça ao desenvolvedor o modelo mental do código, aumentando a confiança e incrementando a produtividade.

Práticas avançadas de desenvolvimento dirigido a testes encaminham para o desenvolvimento dirigido a testes de aceitação (ATDD), onde o critério especificado pelo cliente é automatizado em testes de aceitação, que então levam ao tradicional processo de desenvolvimento dirigido a testes de unidade. Este processo garante que o cliente tem um mecanismo automatizado para decidir como o software atende suas necessidades. Com ATDD, o desenvolvimento em equipe tem objetivo específico para satisfazer, e os testes de aceitação os mantém continuamente focados em o que o cliente realmente deseja daquela funcionalidade.

Benefícios Um estudo de 2005 descobriu que usar TDD significava escrever mais testes, e logo, programadores que escreviam mais testes tendiam a ser mais produtivos. Hipóteses relacionando a qualidade de código e uma correlação direta entre TDD e produtividade foram inconclusivas.

Desenvolvedores usando TDD puramente em novos projetos reportaram que raramente necessitaram a utilização de um depurador. Usado em junção com um Sistema de controle de versão, quando testes falham inesperadamente, reverter o código para a última versão em que os testes passaram pode ser mais produtivo do que depurar.

Desenvolvimento dirigido por testes oferece mais do que somente um maneira simples de validação e de correção, pode orientar o design de um programa. Por focar em casos de testes primeiramente, deve-se imaginar como a funcionalidade será usada pelo cliente. Logo, o programador é somente com a interface e não com a implementação. Este benefício é complementar ao Design por Contrato, que através torna os casos de testes muito mais do que asserções matemáticas ou pré-concepções.

O poder que TDD oferece é a habilidade de pegar pequenas partes quando requeridas. Isso permite o desenvolvedor focar como objetivo fazer os testes atuais passarem. Casos excepcionais e tratamento de erros não são considerados inicialmente. Testes que criam estas circunstâncias estranhas são implementadas separadamente. Outra vantagem é que TDD quando usado apropriadamente, garante que todo o código desenvolvido seja coberto por um teste. Isto fornece a equipe de desenvolvimento, e ao usuários, subsequentemente, um grande nível de confiança ao código.

Enquanto que é verdade que mais código é necessário ao usar TDD do que sem TDD, devido aos códigos de teste, o tempo total de implementação é tipicamente menor. Um grande número de testes ajudam a limitar o número de defeitos no código. A natureza periódica ajuda a capturar defeitos inicialmente no ciclo de desenvolvimento, prevenindo-os de se tornarem grandes e endêmicos problemas. Eliminando defeitos cedo no processo normalmente evita longos e tediantes períodos de depuração posteriores em um projeto.

TDD pode encaminhar a um nível que possibilite um código mais modularizado, flexível e extensível. Este efeito surge devido a metodologia requerer que os desenvolvedores pensem no software em pequenas unidades que podem ser reescritas, desenvolvidas e testadas independentemente e integradas depois. Isto implica menores e mais classes, evitando o acoplamento e permitindo interfaces mais limpas. O uso de Mock Object é um contribuidor para a modularização do código, pois este recurso requer que o código seja escrito de forma que possa ser facilmente trocado entre versões Mock, usados em testes de unidade, e "reais", usados na aplicação.