As pessoas dizem que "falar sobre TDD dificilmente funciona, se você quiser convencer alguém a TDD, mostre-lhes resultados". No entanto, já estou obtendo ótimos resultados sem o TDD. Mostrando que as pessoas que usam TDD obtêm bons resultados não serão convincentes, quero ver que as pessoas que escrevem TDD e não TDD obtêm melhores resultados com TDD.
Apesar de tudo isso, estou interessado em experimentar o TDD. No entanto, não estou convencido de que vou ganhar algo com isso. Se isso for útil, tentarei empurrá-lo para o resto da minha equipe.
Minha principal pergunta é a seguinte: o TDD serviria a algum propósito de código, se eu já puder provar a correção do código?
Obviamente, nenhum deles é uma bala de prata. Sua prova pode estar errada porque você perdeu um detalhe e seu teste pode falhar em detectar um bug que você não testou. No final, somos humanos, ninguém pode criar um código 100% livre de bugs para sempre. Só podemos nos esforçar para chegar o mais perto possível.
No entanto, o TDD realmente economizaria algum tempo em código que tivesse sua correção comprovada? código que, na máquina de estados em que o código opera, todos os possíveis estados válidos e seus intervalos são reconhecidos pelo desenvolvedor, todos são contabilizados e o código é projetado em uma verificação de erro no estilo de lista de permissões que passa todas as exceções para um manipulador superior para garantir que nada de vazamento inesperado -> sem exibir uma mensagem relevante (dentro do motivo) para o cliente e enviar notificações de log para um administrador.
Respostas com exemplos da vida real seriam melhores.
Alguns esclarecimentos:
Esta questão não é sobre se você pode provar a correção do código ou não. Vamos supor, por padrão, que nem todo código possa ser provado correto dentro de um prazo razoável, mas que algumas partes do código podem ser. Por exemplo, é muito fácil comprovar a correção de um módulo FizzBuzz. Não é muito fácil para um serviço de sincronização de dados baseado em nuvem.
Dentro desse limite, a pergunta é a seguinte: Comece com a suposição de que uma base de código é dividida em 2 partes: [I] partes que foram provadas corretas [II] partes que não foram provadas corretas, mas testadas manualmente para funcionar.
Quero aplicar as práticas de TDD a essa base de código que não as possuía até agora. A pergunta é a seguinte: o TDD deve ser aplicado a todos os módulos, ou seria suficiente aplicá-los apenas aos módulos que não se mostraram corretos?
"Comprovado correto" significa que você pode considerar este módulo completamente funcional, ou seja, ele não depende de nenhum estado global ou externo fora de si mesmo, e possui sua própria API de E / S que outros módulos que interagem com ele devem seguir . Não é possível "quebrar este módulo" alterando o código fora do módulo; na pior das hipóteses, você pode usá-lo incorretamente e receber mensagens de erro formatadas.
Obviamente, todas as regras têm exceções; os erros do compilador nas novas versões do compilador podem introduzir erros neste módulo, mas os mesmos erros podem ser introduzidos nos testes que a testaram e resultam em uma falsa sensação de segurança nos testes que não funcionam mais como planejado. A conclusão é que os testes não são uma solução mágica, eles são outra camada de proteção, e esta pergunta discute a questão de saber se essa camada de proteção vale o esforço no caso específico de um módulo que foi provado correto (suponha que foi de fato).
Respostas:
Sim.
As provas são boas quando estão disponíveis, mas mesmo na melhor das hipóteses, elas apenas provam que um único bit de código funcionará conforme o esperado (para todas as entradas - responsável por interrupções no meio de qualquer operação - e quanto à falta de memória ? falha no disco? falha na rede?).
O que acontece quando muda?
Os testes são ótimos porque servem como um contrato implícito sobre o que o código deve fazer. Eles fornecem alguns andaimes para que seu novo estagiário possa entrar e fazer alterações com algum nível de confiança. Tudo através de resultados rápidos e claros: passa ou falha.
E, francamente, posso treinar um estagiário para escrever testes de unidade viáveis em alguns meses. Duvido que alguém da minha equipe (inclusive eu) possa criar provas que garantam algo significativo para código não trivial; e muito menos fazê-lo com rapidez e precisão.
fonte
For large & rapidly changing projects
quanto mais propensos a mudar, mais necessários são os testes, pois um código alterado tem muito mais chances de falhar devido a novos erros ou comportamentos inesperados do que o código que mal muda. É uma questão de probabilidade. Mesmo que não mude com frequência, após algum tempo o conhecimento obtido durante o desenvolvimento pode se perder ou cair no esquecimento. Os testes também são conhecimentos materializados, que podem reduzir significativamente a curva de aprendizado. Os testes de codificação são demorados? Sim. Isso torna o projeto mais caro? Não, a longo prazo torne mais barato .Nós não sabemos. Não podemos responder à sua pergunta.
Enquanto você gasta muito tempo explicando esse processo que agora parece funcionar para a satisfação de todos, você está nos dizendo apenas uma pequena fatia do que realmente está acontecendo.
Pela minha experiência, o que você está descrevendo é extrema raridade e eu sou cético quanto ao fato de que o processo e a abordagem de codificação são realmente causa de baixa contagem de bugs em seus aplicativos. Pode haver muitos outros fatores que influenciam seus aplicativos e você não está nos dizendo nada sobre esses fatores.
Portanto, não sabemos, apesar de não conhecermos exatamente o seu ambiente e cultura de desenvolvimento, se o TDD o ajudará ou não. E podemos passar dias discutindo e discutindo sobre isso.
Há apenas uma recomendação que podemos oferecer: experimente. Experimentar. Aprenda. Eu sei que você está tentando gastar menos esforço para decidir, mas isso não é possível. Se você realmente quer saber se o TDD funcionará no seu contexto, a única maneira de descobrir é realmente fazer o TDD. Se você realmente aprender e aplicá-lo ao seu aplicativo, poderá compará-lo com o seu processo não TDD. Pode ser que o TDD realmente tenha vantagens e você decida mantê-lo. Ou então, o TDD não traz nada de novo e apenas o atrasa. Nesse caso, você pode voltar ao processo anterior.
fonte
O principal objetivo dos testes (unitários) é proteger o código, garantindo que ele não seja despercebido devido a alterações posteriores. Quando o código é escrito pela primeira vez, ele recebe muita atenção e é examinado. E você pode ter algum sistema superior para isso.
Seis meses depois, quando alguém estiver trabalhando em algo aparentemente não relacionado, ele poderá se romper e o seu superprovedor de correção de código não notará. Um teste automático será.
fonte
Esta é a maneira mais difícil de aprender TDD. Quanto mais tarde você testar, mais custará escrever testes e menos você os escreverá.
Não estou dizendo que é impossível adaptar os testes a uma base de código existente. Estou dizendo que isso provavelmente não transformará ninguém em um crente no TDD. Isso é trabalho duro.
Na verdade, é melhor praticar TDD pela primeira vez em algo novo e em casa. Dessa forma, você aprende o ritmo real. Faça isso da maneira certa e você achará viciante.
Esse é o pensamento estrutural. Você não deve dizer coisas como testar todas as funções, classes ou módulos. Esses limites não são importantes para o teste e devem poder mudar de qualquer maneira. TDD é estabelecer uma necessidade comportamental testável e não se importar com a satisfação. Se não fosse, não poderíamos refatorar.
É suficiente aplicá-los onde você achar necessário. Eu começaria com um novo código. Você obterá muito mais retorno dos testes mais cedo do que tarde. Não faça isso no trabalho até ter praticado o suficiente para dominá-lo em casa.
Quando você mostrar que o TDD é eficaz com o novo código no trabalho e se sentir confiante o suficiente para aceitar o código antigo, eu começaria com o código comprovado. O motivo é porque você poderá ver imediatamente se os testes que está escrevendo estão levando o código em uma boa direção.
Os testes não apenas provam a exatidão. Eles mostram intenção. Eles mostram o que é necessário. Eles apontam um caminho para mudar. Um bom teste diz que existem várias maneiras de escrever esse código e obter o que você deseja. Eles ajudam os novos codificadores a ver o que podem fazer sem quebrar tudo.
Somente quando você tiver esse problema, deverá entrar no código não comprovado.
Um aviso contra os fanáticos: você parece ter alcançado sucesso e, portanto, é improvável que dê um pulo na frente. Mas outros que procuram provar a si mesmos não serão tão reservados. TDD pode ser exagerado. É incrivelmente fácil criar um conjunto de testes que realmente prejudica a refatoração porque bloqueiam coisas triviais e sem sentido. Como isso acontece? Porque as pessoas que procuram exibir testes apenas escrevem testes e nunca refatoram. Solução? Faça-os refatorar. Faça-os lidar com mudanças de recursos. Quanto antes melhor. Isso mostrará os testes inúteis rapidamente. Você prova flexibilidade flexionando.
Um aviso contra a categorização estrutural: algumas pessoas insistem que uma classe é uma unidade. Alguns chamarão qualquer teste com duas classes de teste de integração. Alguns insistem que você não pode cruzar o limite x e chamar isso de teste de unidade. Em vez de me preocupar com nada disso, aconselho que você se preocupe com o comportamento do seu teste. Ele pode ser executado em uma fração de segundo? Pode ser executado em paralelo com outros testes (sem efeitos colaterais)? Pode ser executado sem iniciar ou editar outras coisas para satisfazer dependências e pré-condições? Ponho essas considerações à frente se ele se relacionar com um banco de dados, sistema de arquivos ou rede. Por quê? Porque esses três últimos são apenas problemas porque causam os outros problemas. Agrupe seus testes com base em como você pode esperar que eles se comportem. Não são os limites que eles cruzam. Então você sabe o que pode esperar que cada suíte de testes faça.
Essa pergunta já tem respostas aqui .
fonte
O Desenvolvimento Orientado a Testes é mais sobre prototipagem e brainstorming de uma API do que testes. Os testes criados geralmente são de baixa qualidade e, eventualmente, precisam ser descartados. A principal vantagem do TDD é determinar como uma API será usada antes de escrever a implementação da API. Essa vantagem também pode ser obtida de outras maneiras, por exemplo, escrevendo a documentação da API antes da implementação.
As provas de correção são sempre mais valiosas que os testes. Os testes não provam nada. No entanto, para usar provas de correção de maneira produtiva, é útil ter um verificador automático de provas, e você precisará trabalhar com contratos de algum tipo (design por contrato ou design baseado em contrato).
No passado, ao trabalhar em seções críticas do código, tentava provas manuais de correção. Até as provas informais são mais valiosas do que qualquer teste automatizado. Mas você ainda precisa dos testes, a menos que possa automatizar suas provas, pois as pessoas quebrarão seu código no futuro.
Testes automatizados não implicam TDD.
fonte
String getSomeValue()
aqui para que possamos testá-lo" quando isso não faz sentido para o design geral. Claro, você pode remover essa função mais tarde, mas, na minha experiência, isso é raro.A) Você está lendo o código e se convencendo de que ele está correto não é nem remotamente próximo de provar que está correto. Caso contrário, por que escrever testes?
B) Quando você altera o código, deseja executar testes que demonstram que o código ainda está correto ou não.
fonte
Vou fazer uma ressalva dizendo que, uma vez que você esteja acostumado a usar o TDD efetivamente, você economizará tempo no final do jogo. É preciso prática para aprender a usar o TDD efetivamente, e não ajuda quando você está com problemas de tempo. Ao aprender a melhor forma de usá-lo, recomendo iniciar um projeto pessoal em que você tenha mais liberdade e menos pressão no cronograma.
Você verá que seu progresso inicial é mais lento enquanto você está experimentando mais e escrevendo sua API. Com o tempo, seu progresso será mais rápido à medida que seus novos testes começarem a passar sem alterar o código, e você terá uma base muito estável para construir. No final do jogo, o código que não é criado usando o TDD exige que você gaste muito mais tempo no depurador enquanto tenta descobrir o que está errado do que seria necessário. Você também corre um risco maior de quebrar algo que costumava trabalhar com novas mudanças. Avalie a eficácia do TDD vs. não o use pelo tempo total até a conclusão.
Dito isto, TDD não é o único jogo na cidade. Você pode usar o BDD, que usa uma maneira padrão de expressar o comportamento de um aplicativo de pilha completa e avaliar a correção da API a partir daí.
Todo o seu argumento depende de "provar a exatidão do código", então você precisa de algo que defina a correção do código. Se você não estiver usando uma ferramenta automatizada para definir o que "correto" significa, a definição é muito subjetiva. Se sua definição de correto é baseada no consenso de seus colegas, isso pode mudar em qualquer dia. Sua definição de correto precisa ser concreta e verificável, o que também significa que deve poder ser avaliado por uma ferramenta. Por que não usar um?
A vitória nº 1 do uso de testes automatizados de qualquer tipo é que você pode verificar se seu código permanece correto mesmo quando os patches do sistema operacional são aplicados de maneira rápida e eficiente. Execute seu conjunto para garantir que tudo esteja passando, aplique o patch e execute o conjunto novamente. Melhor ainda, faça parte da sua infraestrutura de construção automatizada. Agora você pode verificar se seu código permanece correto após mesclar o código de vários desenvolvedores.
Minha experiência com o TDD me levou às seguintes conclusões:
Minha experiência com o BDD me levou às seguintes conclusões:
Definição de correto: seu código está em conformidade com os requisitos. Isso é melhor verificado com o BDD, que fornece um meio de expressar esses requisitos de maneira legível por humanos e verificá-los em tempo de execução.
Não estou falando de correção em termos de provas matemáticas, o que não é possível. E estou cansado de ter esse argumento.
fonte