Compreendo o desenvolvimento orientado a testes até o momento em que você só pode escrever código produtivo quando tiver um teste de unidade (vermelho) com falha. Com base nisso, tenho a pergunta se a abordagem orientada a testes também pode ser aplicada a outras formas de testes.
41
Respostas:
Tudo o que o TDD exige de você é que você escreva um teste com falha e modifique seu código para fazê-lo passar.
Normalmente, os "testes de unidade" são pequenos e rápidos e testam parte de seu código isoladamente. Por serem rápidos, também faz o loop vermelho / verde / refatorar rapidamente. No entanto, eles sofrem apenas com peças de teste isoladas. Então você precisa de outros testes também (integração, aceitação etc). Ainda é uma boa prática seguir os mesmos princípios: escreva um teste com falha e modifique o código para fazê-lo funcionar. Esteja ciente de que eles geralmente são mais lentos, pois isso pode afetar o tempo do ciclo de vermelho / verde / refatorar.
fonte
O ciclo do refator verde vermelho baseia-se em um princípio muito sólido:
Confie apenas nos testes que você viu passar e falhar.
Sim, isso também funciona com testes de integração automatizados. Também testes manuais. Heck, ele funciona em testadores de bateria de carro. É assim que você testa o teste.
Alguns acham que os testes de unidade cobrem a menor coisa que pode ser testada. Alguns pensam em algo que é rápido para testar. O TDD é mais do que apenas o ciclo do refator verde vermelho, mas essa parte tem um conjunto muito específico de testes: não são os testes que você idealmente executará uma vez antes de enviar uma coleção de alterações. São os testes que você executará toda vez que fizer alguma alteração. Para mim, esses são seus testes de unidade.
fonte
Sim, e uma abordagem bem conhecida que faz isso é o desenvolvimento orientado pelo comportamento . Os testes gerados a partir das especificações formais no BDD podem ser chamados de "testes de unidade", mas normalmente não são tão baixos quanto no TDD real, provavelmente se ajustam melhor ao termo "testes de aceitação".
fonte
Não. Você só pode escrever o código mais simples possível para alterar a mensagem do teste. Não diz nada sobre que tipo de teste.
De fato, você provavelmente começará escrevendo um teste de aceitação com falha (vermelho) para um critério de aceitação; mais precisamente, você escreverá o teste de aceitação mais simples que pode falhar; depois de executar o teste, observe-o falhar e verifique se ele falha pelo motivo certo. Em seguida, você escreve um teste funcional com falha para obter uma fatia da funcionalidade desse critério de aceitação; novamente, você escreve o teste funcional mais simples que pode falhar, executa-o, observa-o falhar e verifica se ele falha pelo motivo certo. Em seguida, você escreve um teste de unidade com falha, o teste de unidade mais simples que pode falhar, executa-o, assista-o falhar, verifique se ele falha pelo motivo certo.
Agora , você escreve o código de produção mais simples que pode alterar a mensagem de erro. Execute o teste novamente, verifique se a mensagem de erro foi alterada, se foi na direção correta e se o código alterou a mensagem pelo motivo correto. (Idealmente, a mensagem de erro já deve ter saído e o teste deve passar, mas, na maioria das vezes, é melhor tomar pequenas etapas para alterar a mensagem em vez de tentar fazer o teste passar de uma só vez - essa é a razão por que os desenvolvedores de estruturas de teste gastam tanto esforço em suas mensagens de erro!)
Depois de passar no teste de unidade, você refatora seu código de produção sob a proteção de seus testes. (Observe que, no momento, o teste de aceitação e o teste funcional ainda estão falhando, mas tudo bem, já que você está refatorando apenas unidades individuais cobertas por testes de unidade.)
Agora você cria o próximo teste de unidade e repita o procedimento acima, até que o teste funcional também passe. Sob a proteção do teste funcional, agora você pode fazer refatorações em várias unidades.
Esse ciclo intermediário agora se repete até que o teste de aceitação seja aprovado; nesse momento, você pode fazer refatorações em todo o sistema.
Agora, você escolhe o próximo critério de aceitação e o ciclo externo inicia novamente.
Kent Beck, o "descobridor" do TDD (ele não gosta do termo "inventor", ele diz que as pessoas fazem isso o tempo todo, ele apenas deu um nome e escreveu um livro sobre ele) usa uma analogia da fotografia e chama isso de "aumentar e diminuir o zoom".
Nota: você nem sempre precisa de três níveis de testes. Talvez, às vezes você precise de mais. Mais frequentemente, você precisa de menos. Se suas peças de funcionalidade são pequenas e seus testes funcionais são rápidos, você pode passar sem (ou com menos testes de unidade). Muitas vezes, você só precisa de testes de aceitação e testes de unidade. Ou, seus critérios de aceitação são tão refinados que seus testes de aceitação são funcionais.
Kent Beck diz que, se ele tiver um teste funcional rápido, pequeno e focado, ele primeiro escreverá os testes de unidade, permitirá que os testes de unidade conduzam o código e exclua (alguns) os testes de unidade novamente que abrangem o código que também é coberto pelo teste funcional rápido. Lembre-se: o código de teste também é um código que precisa ser mantido e refatorado, quanto menos houver, melhor!
Você realmente não aplica o TDD aos testes. Você o aplica a todo o processo de desenvolvimento. É isso que significa a parte "orientada" do Desenvolvimento Orientado a Testes : todo o seu desenvolvimento é orientado por testes. Os testes não apenas orientam o código que você escreve, mas também o código a ser escrito, o código a ser escrito a seguir. Eles dirigem o seu design. Eles dizem quando você termina. Eles dizem a você o que trabalhar a seguir. Eles falam sobre falhas de design no seu código (quando é difícil escrever testes).
Keith Braithwaite criou um exercício que ele chama de TDD como se você quisesse . Consiste em um conjunto de regras (baseadas nas Três Regras do TDD do tio Bob Martin , mas muito mais rigorosas) que você deve seguir rigorosamente e que foram projetadas para orientá-lo a aplicar o TDD com mais rigor. Funciona melhor com a programação de pares (para que seu par possa garantir que você não está infringindo as regras) e com um instrutor.
As regras são:
Essas regras são destinadas ao exercício do TDD. Eles não foram feitos para realmente fazer TDD na produção (embora nada o impeça de testá-lo). Eles podem se sentir frustrantes porque às vezes parecerá que você dá milhares de pequenos passos sem fazer nenhum progresso real.
fonte
O TDD não se limita ao que a comunidade tradicional de Teste de Software chama de "teste de unidade". Esse mal-entendido muito comum é o resultado da infeliz sobrecarga de Kent Beck do termo "unidade" ao descrever sua prática de TDD. O que ele quis dizer com "teste de unidade" era um teste executado isoladamente. Não depende de outros testes. Cada teste deve configurar o estado de que precisa e fazer qualquer limpeza quando terminar. É nesse sentido que um teste de unidade no sentido TDD é uma unidade. É independente. Ele pode ser executado sozinho ou em conjunto com qualquer outro teste de unidade em qualquer ordem.
Referência : "Desenvolvimento Orientado a Testes por Exemplo", de Kent Beck
Kent Beck descreve o que ele entende por “teste de unidade” no Capítulo 32 - Domínio do TDD
fonte
Eu não li livros sobre isso nem sigo completamente as práticas TDD "padrão" o tempo todo, mas, na minha opinião, o ponto principal da filosofia do TDD, com o qual eu concordo completamente, é que você precisa definir o sucesso primeiro . Isso é importante em todos os níveis de design, em "Qual é o objetivo deste projeto?" para "Quais devem ser as entradas e saídas deste pequeno método?"
Existem várias maneiras de fazer essa definição de sucesso. Um método útil, especialmente para os métodos de baixo nível com potencialmente muitos casos extremos, é escrever testes em código. Para alguns níveis de abstração, pode ser útil apenas escrever uma nota rápida sobre o objetivo do módulo ou o que quer que seja, ou até mesmo verificar-se mentalmente (ou pedir a um colega de trabalho) para garantir que tudo faça sentido e esteja de acordo. lugar lógico. Às vezes, é útil descrever um teste de integração no código (e, é claro, que ajuda a automatizá-lo), e às vezes é útil apenas definir um plano de teste rápido razoável que você pode usar para garantir que todos os sistemas estejam trabalhando juntos da maneira que você estão esperando.
Mas, independentemente das técnicas ou ferramentas específicas que você está usando, na minha opinião, o principal a tirar da filosofia do TDD é que definir o sucesso acontece primeiro. Caso contrário, você está jogando o dardo e depois pintando o alvo em qualquer lugar em que aconteceu.
fonte
Na palestra Desenvolvimento Orientado a Testes: Não foi isso que quisemos dizer Steve Freeman mostra o seguinte slide do quadro geral do TDD (veja a imagem abaixo resposta). Isso inclui uma etapa "Escreva um teste de ponta a ponta com falha", que é seguida por "Escreva um teste de unidade com falha". (Clique para ampliar, no canto superior direito)
Portanto, não no TDD, os testes nem sempre são testes de unidade.
E sim, você pode (e talvez deva) começar com um teste de ponta a ponta de nível superior que falha antes de escrever seu primeiro teste de unidade. Este teste descreve o comportamento que você deseja alcançar. Isso gera cobertura em mais níveis da pirâmide de teste . Adrian Sutton explica a experiência do LMAX, que mostra que os testes de ponta a ponta podem desempenhar um papel grande e valioso .
fonte
Não, não pode ser aplicado a outros tipos de testes, por uma simples razão prática: outros tipos de testes estão demorando muito para serem executados.
O ciclo TDD típico é: escrever teste com falha, implementar, refatorar o código. As etapas intermediárias são a construção e a execução de testes, e eles precisam ser extremamente rápidos. Se não estiverem, as pessoas começarão a pular as etapas e você não estará mais executando o TDD.
fonte