Sou um novo programador (só aprendo há cerca de um ano) e, no meu objetivo de melhorar, aprendi recentemente sobre o TDD. Eu queria adquirir o hábito de usá-lo, pois parece muito útil. Eu queria verificar e ter certeza de que estou usando corretamente.
O que eu estou fazendo:
- Pense em um novo método que eu preciso.
- Crie um teste para esse método.
- Falhar no teste.
- Escreva método.
- Teste de passagem.
- Refatorar método.
- Repetir.
Estou fazendo isso para todo método que escrevo, há alguns que não devo me preocupar? Mais tarde, costumo pensar em uma maneira de testar meus métodos já existentes de uma maneira ou situação diferente. Devo fazer esses novos testes, ou como cada método já possui um teste próprio, não devo me preocupar? Posso testar o meu código? Acho que é a minha principal preocupação ao fazer isso.
EDITAR
Além disso, isso era algo que eu estava pensando. Ao fazer algo como criar uma GUI, o TDD seria necessário nessa situação? Pessoalmente, não consigo pensar em como escreveria testes para isso.
Respostas:
O que você está descrevendo como um fluxo de trabalho não é, na minha opinião, o Spirit of TDD.
A sinopse do livro de Kent Becks na Amazon diz:
TDD prático
Teste formal automatizado, especialmente Teste de unidade, todos os métodos de todas as classes são tão antipadrão quanto não testam nada. Há um equilíbrio a ser tido. Você está escrevendo testes de unidade para todos os
setXXX/getXXX
métodos, eles também são métodos!Os testes também podem ajudar a economizar tempo e dinheiro, mas não esqueça que eles custam tempo e dinheiro para serem desenvolvidos e são código, portanto, eles custam tempo e dinheiro para serem mantidos. Se atrofiam por falta de manutenção, tornam-se um passivo mais que um benefício.
Como tudo isso, existe um equilíbrio que não pode ser definido por ninguém além de você. Qualquer dogma de qualquer maneira é provavelmente mais errado do que correto.
Uma boa métrica é um código que é crítico para a lógica de negócios e sujeito a modificações frequentes com base nos requisitos variáveis. Essas coisas precisam de testes formais automatizados, que seriam um grande retorno do investimento.
Você vai ser muito pressionado a encontrar muitas lojas profissionais que funcionam dessa maneira também. Simplesmente não faz sentido para os negócios gastar dinheiro testando coisas que, para todos os efeitos práticos, nunca mudam após a realização de um simples teste de fumaça. Escrever testes de unidade automatizados formais para
.getXXX/.setXXX
métodos é um excelente exemplo disso, completa perda de tempo.Veja também esta resposta .
fonte
setXXX/getXXX
não são necessários em todos os :)Você está muito perto. Tente pensar desta maneira um pouco diferente.
Não crie getters e setters automaticamente para cada propriedade . Não pense em um método inteiro e escreva os testes para cobrir todas as funcionalidades . Tente encapsular as propriedades dentro da classe e escreva métodos para fornecer o comportamento necessário. Deixe seus métodos evoluírem para um bom design, em vez de tentar planejá-los com antecedência. Lembre-se de que o TDD é um processo de design, não um processo de teste. A vantagem que ele tem sobre outros processos de design é deixar para trás um fluxo de testes de regressão automatizados, em vez de um pedaço de papel que você joga na lixeira.
Lembre-se também das três regras de TDD do tio Bob .
fonte
Poucas coisas a serem adicionadas às respostas de outras pessoas:
Existe um excesso de teste. Você deseja garantir que seus testes de unidade se sobreponham o mínimo possível. Não faz sentido que vários testes verifiquem as mesmas condições no mesmo trecho de código. Por outro lado, quando você refatorar seu código de produção e tiver muitos testes que se sobrepõem a essa seção, precisará voltar e corrigir todos esses testes. Enquanto que, se não se sobrepuserem, uma alteração interromperá no máximo apenas um teste.
Só porque você pensou em uma maneira melhor de escrever um teste, eu não voltaria lá e começaria a reescrevê-lo. Isso remonta aos indivíduos que continuam escrevendo e reescrevendo a mesma classe / função, porque tentam aperfeiçoá-lo. Nunca será perfeito, então siga em frente. Quando você descobrir um método melhor, mantenha-o em mente (ou adicione aos comentários do teste). Da próxima vez que estiver lá, e você perceber o benefício imediato de mudar para o novo caminho, é hora de refatorar. Caso contrário, se o recurso estiver pronto e você seguir em frente e tudo funcionar, deixe-o funcionando.
O TDD se concentra em fornecer valor imediato, não apenas em garantir que todas as funções sejam testáveis. Quando você adiciona funcionalidade, comece perguntando "do que o cliente precisa". Em seguida, defina uma interface para fornecer ao cliente o que ele precisa. Em seguida, implemente o que for necessário para fazer o teste passar. O TDD é quase como testar cenários de casos de uso (incluindo todos os "what-ifs"), em vez de simplesmente codificar funções públicas e testar cada uma.
Você perguntou sobre o teste do código da GUI. Procure os padrões "Humble Dialog" e "MVVM". A idéia por trás de ambas é que você crie um conjunto de classes "modelo de exibição", que na verdade não possuem lógica específica da interface do usuário. No entanto, essas classes terão toda a lógica de negócios que normalmente faz parte da sua interface do usuário e essas classes devem ser 100% testáveis. O que resta é um shell de interface do usuário muito fino e, sim, normalmente esse shell é deixado sem cobertura de teste, mas nesse momento ele deve ter quase nenhuma lógica.
Se você possui uma grande parte do código existente, como sugeriram alguns outros, não deve começar a adicionar testes de unidade absolutamente em todos os lugares. Levará uma eternidade e você não se beneficiará da adição de testes de unidade a 80% das classes que são estáveis e não serão alteradas no futuro próximo (ou não tão próximo). No entanto, para novos trabalhos, acho que o uso do desenvolvimento TDD com o código ALL é extremamente benéfico. Você não apenas termina com um conjunto com testes automatizados quando termina, mas o desenvolvimento real tem enormes benefícios:
fonte
Existem alguns métodos que não estão sendo testados, a saber, esses testes. No entanto, há algo a ser dito para alguns testes serem adicionados após a gravação do código inicial, como condições de contorno e outros valores, para que possa haver vários testes em um único método.
Embora você possa testar demais o seu código, isso geralmente acontece quando alguém deseja testar todas as permutações possíveis de entradas que não soem exatamente como o que você está fazendo. Por exemplo, se você possui um método que utiliza um caractere, escreve um teste para todos os valores possíveis que podem ser inseridos? É aí que você chegará ao super teste, IMO.
fonte
Geralmente você está fazendo certo.
Testes são código. Portanto, se você pode melhorar o teste, vá em frente e refatorá-lo. Se você acha que um teste pode ser aprimorado, vá em frente e mude. Não tenha medo de substituir um teste por um melhor.
Eu recomendo ao testar seu código, evite especificar como o código deve fazer o que está fazendo. Os testes devem observar os resultados dos métodos. Isso ajudará na refatoração. Alguns métodos não precisam ser testados explicitamente (por exemplo, getters e setters simples) porque você os utilizará para verificar os resultados de outros testes.
fonte
Minha opinião sobre o TDD é que as ferramentas criaram um mundo de desenvolvedores de estilo 'aponte e clique'. Só porque as ferramentas criam um esboço de teste para cada método não significa que você deve escrever testes para cada método. Algumas pessoas estão 'renomeando' o TDD como BDD (desenvolvimento orientado ao comportamento), onde os testes são muito mais detalhados e pretendem testar o comportamento da classe, e não cada método complicado.
Se você projeta seus testes para testar a classe como se destina a ser usada, começa a obter alguns benefícios, especialmente quando começa a escrever testes que exercem um pouco mais do que cada método, especialmente quando você começa a testar a interação daqueles métodos. Suponho que você possa pensar nisso como escrever testes para uma classe, em vez de métodos. De qualquer forma, você ainda deve escrever 'testes de aceitação' que exercitem a combinação de métodos para garantir que não haja contradições ou conflitos na maneira como são usados juntos.
Não confunda TDD com teste - não é. O TDD foi projetado para que você escreva código para exercitar seus requisitos, não para testar os métodos. É um ponto sutil, mas importante, que muitas vezes se perde nas pessoas que escrevem cegamente o código de teste para todos os métodos. É que você deve escrever testes para garantir que seu código faça o que você quer que ele faça, não que o código que você escreveu funcione como deveria.
Existem alguns bons links à direita sobre o BDD x TDD. Vê-los.
fonte
Ao começar a aprender TDD, sim, você deve seguir cegamente a abordagem dogmática de não escrever uma única linha de código, exceto para fazer um teste com falha, e escrever apenas um teste suficiente para falhar (e falhar pelo motivo certo / esperado) .
Depois de aprender o que é o TDD, ENTÃO você pode decidir que certos tipos de coisas não valem a pena testar. Esta é a mesma abordagem que você deve seguir para tudo, e as artes marciais japonesas chamam isso de " shuhari ". (O link também explica como se pode progredir nos estágios de aprendizado sem um professor, que é, suspeito, como a maioria das pessoas precisa aprender.)
fonte
Eu acredito que você está testando demais.
Pratico TDD há muitos anos e, na minha experiência, quando o TDD é realizado de maneira eficaz, você obtém dois benefícios principais:
Fornecer feedback rápido
Particularmente em linguagens dinâmicas, eu posso executar os testes relevantes em menos de um segundo. E eu tenho observadores do sistema de arquivos executando esses testes automaticamente quando um arquivo de origem é alterado no disco. Portanto, praticamente não tenho tempo de espera para testes e sei imediatamente se o código que escrevi foi o esperado. Assim, o TDD leva a uma maneira muito eficiente de trabalhar.
Ativar refatoração
Se você possui um bom conjunto de testes, pode refatorar com segurança, à medida que obtém novas idéias sobre como o sistema deve ser projetado.
Um bom conjunto de testes permite que você mova a responsabilidade pelo código e ainda tenha confiança de que o código funcionará conforme o esperado após a movimentação. E você deve conseguir fazer isso com pequenas alterações no código de teste.
Se você escrever testes para todos os métodos do seu sistema, é provável que você não consiga refatorar facilmente seu código, pois cada refator de código exigirá grandes alterações no código de teste. E você pode ter certeza de que o código de teste ainda funciona conforme o esperado? Ou você introduziu acidentalmente um erro no código de teste, o que consequentemente leva a um erro no código de produção?
Se você, no entanto, como também sugerido na resposta da pdr , concentre-se no comportamento em vez de nos métodos ao escrever testes, você terá testes que exigirão muito menos alterações ao refatorar o sistema.
Ou, como Ian Cooper diz nesta apresentação (citei de memória, talvez não seja corretamente citado):
fonte
Você deve testar todos os métodos públicos .
O problema aqui é que, se seus métodos públicos são muito pequenos, você provavelmente está expondo muita informação. A prática comum de expor todas as propriedades como
getXXX()
realmente quebra o encapsulamento.Se seus métodos públicos são realmente o comportamento da classe, você deve testá-los. Caso contrário, eles não são bons métodos públicos.
EDIT: a resposta do pdr é muito mais completa que a minha.
fonte