Sou um desenvolvedor solo com um ambiente de trabalho bastante limitado, onde o tempo de desenvolvimento geralmente varia de 1 a 4 semanas por projeto, dependendo dos requisitos, urgência ou ambos. A qualquer momento, lida com 3-4 projetos, alguns com cronogramas que se sobrepõem.
Espera-se que a qualidade do código sofra. Eu também não tenho teste formal; geralmente passa a andar pelo sistema até que se quebre um pouco. Como resultado, uma quantidade considerável de erros escapa à produção, que eu tenho que corrigir e, por sua vez, atrasa meus outros projetos.
É aqui que entra o teste de unidade. Quando bem feito, ele deve conter bugs, muito menos aqueles que escapam à produção, no mínimo. Por outro lado, escrever testes pode levar uma quantidade considerável de tempo, o que não soa bem em projetos com tempo limitado, como o meu.
A pergunta é: quanto de diferença de tempo seria escrever código testado em unidade sobre código não testado e como essa diferença de tempo aumenta conforme o escopo do projeto aumenta?
fonte
Respostas:
Quanto mais tarde você testar, mais custará escrever testes.
Quanto mais tempo um bug permanecer, mais caro será o reparo.
A lei dos rendimentos decrescentes garante que você possa testar seu esquecimento tentando garantir que não haja bugs.
Buda ensinou a sabedoria do caminho do meio. Os testes são bons. Existe uma coisa boa demais. A chave é poder saber quando você está desequilibrado.
Cada linha de código que você escreve sem testes terá custos significativamente maiores para adicionar testes posteriormente do que se você tivesse escrito os testes antes de escrever o código.
Cada linha de código sem testes será significativamente mais difícil de depurar ou reescrever.
Cada teste que você escreve leva tempo.
Todo bug levará tempo para ser corrigido.
Os fiéis lhe dirão para não escrever uma única linha de código sem antes escrever um teste que falhou. O teste garante que você esteja obtendo o comportamento esperado. Ele permite que você altere o código rapidamente, sem se preocupar em afetar o resto do sistema, pois o teste prova que o comportamento é o mesmo.
Você deve pesar tudo isso contra o fato de que os testes não adicionam recursos. O código de produção adiciona recursos. E os recursos são o que paga as contas.
Pragmaticamente falando, adiciono todos os testes com os quais posso me safar. Ignoro comentários a favor de assistir a testes. Eu nem confio no código para fazer o que acho que faz. Eu confio em testes. Mas sou conhecido por jogar ocasionalmente Mary e ter sorte.
No entanto, muitos codificadores de sucesso não fazem TDD. Isso não significa que eles não testam. Eles simplesmente não insistem obsessivamente que toda linha de código tenha um teste automatizado contra ela. Até o tio Bob admite que não testa sua interface do usuário. Ele também insiste em que você mova toda a lógica da interface do usuário.
Como uma metáfora do futebol (o futebol americano), o TDD é um bom jogo de chão. O teste apenas manual, onde você escreve uma pilha de código e espera que funcione, é um jogo que está passando. Você pode ser bom em qualquer um. Sua carreira não fará os playoffs, a menos que você possa fazer as duas coisas. Não será o superbowl até que você aprenda quando escolher cada um. Mas se você precisar de um empurrão em uma direção específica: os telefonemas das autoridades vão contra mim com mais frequência quando estou passando.
Se você quiser experimentar o TDD, recomendo que você pratique antes de tentar fazê-lo no trabalho. O TDD feito pela metade, meio coração e meio jumento é uma grande razão pela qual alguns não o respeitam. É como derramar um copo de água em outro. Se você não se comprometer e fazê-lo rápida e completamente, você acaba pingando água por toda a mesa.
fonte
Concordo com o restante das respostas, mas com a resposta direta à pergunta sobre a diferença horária .
Roy Osherove, em seu livro The Art of Unit Testing, Segunda Edição, página 200, fez um estudo de caso da implementação de projetos de tamanho semelhante com equipes semelhantes (em termos de habilidade) para dois clientes diferentes, onde uma equipe testou enquanto a outra não.
Seus resultados foram assim:
Portanto, no final de um projeto, você obtém menos tempo e menos erros. Obviamente, isso depende do tamanho de um projeto.
fonte
Conheço apenas um estudo que estudou isso em um "cenário do mundo real": percebendo a melhoria da qualidade através do desenvolvimento orientado a testes: resultados e experiências de quatro equipes industriais . É caro fazer isso de uma maneira sensata, pois basicamente significa que você precisa desenvolver o mesmo software duas vezes (ou idealmente com mais frequência) com equipes semelhantes e depois jogar tudo fora um.
Os resultados do estudo foram um aumento no tempo de desenvolvimento entre 15% a 35% (que não chega nem perto do valor de 2x que é frequentemente citado pelos críticos do TDD) e uma diminuição na densidade de defeitos antes da liberação de 40% a 90% (! ) Observe que todas as equipes não tinham experiência anterior com TDD, portanto, pode-se supor que o aumento no tempo possa ser pelo menos parcialmente atribuído ao aprendizado e, portanto, diminuiria ainda mais ao longo do tempo, mas isso não foi avaliado pelo estudo.
Observe que este estudo é sobre TDD e sua pergunta é sobre testes de unidade, que são coisas muito diferentes, mas é o mais próximo que pude encontrar.
fonte
null
, funcional acima do imperativo, contratos de código, análise estática, refatoração automática, sem contêineres IoC (exceto DI) etc. Aposto que esse valor de testes unitários diminuiria (mas não desapareceria).Feito bem, o desenvolvimento com testes de unidade pode ser mais rápido, mesmo sem considerar os benefícios de bugs extras serem capturados.
O fato é que eu não sou um codificador bom o suficiente para simplesmente fazer com que meu código funcione assim que ele for compilado. Quando escrevo / modifico o código, tenho que executá-lo para garantir que ele faça o que eu pensava. Em um projeto, isso tendia a se parecer com:
E, é claro, depois de tudo isso, geralmente eram necessárias algumas viagens de ida e volta para realmente acertar.
Agora, e se eu estiver usando testes de unidade? Em seguida, o processo se parece mais com:
Isso é mais fácil e rápido do que testar manualmente o aplicativo. Eu ainda tenho que executar manualmente o aplicativo (para não parecer bobo quando entrego um trabalho que realmente não funciona), mas na maioria das vezes eu já resolvi as torções, e estou apenas verificando nesse ponto. Na verdade, normalmente faço esse loop ainda mais apertado usando um programa que executa novamente meus testes automaticamente quando eu salvo.
No entanto, isso depende do trabalho em uma base de código amigável para teste. Muitos projetos, mesmo aqueles com muitos testes, dificultam os testes de escrita. Mas se você trabalhar nisso, poderá ter uma base de código mais fácil de testar através de testes automatizados do que com testes manuais. Como bônus, você pode manter os testes automatizados por perto e executá-los para evitar regressões.
fonte
Apesar de já haver muitas respostas, elas são um tanto repetitivas e eu gostaria de adotar uma abordagem diferente. Os testes de unidade são valiosos, se e somente se , aumentam o valor comercial . Testar por testes (testes triviais ou tautológicos), ou para atingir alguma métrica arbitrária (como cobertura de código), é uma programação de cultos de carga.
Os testes são caros, não apenas no tempo necessário para escrevê-los, mas também na manutenção. Eles precisam ser mantidos sincronizados com o código que testam ou são inúteis. Sem mencionar o custo de tempo para executá-los em todas as alterações. Isso não é uma quebra de negócio (ou uma desculpa para não fazer os realmente necessários), mas precisa ser levado em consideração na análise de custo-benefício.
Portanto, a pergunta a ser feita ao decidir se deve ou não (ou de que tipos) testar uma função / método, pergunte a si mesmo 'que valor para o usuário final estou criando / protegendo com este teste?'. Se você não puder responder a essa pergunta, de cabeça para baixo, provavelmente esse teste não vale o custo de escrever / manter. (ou você não entende o domínio do problema, que é um problema muitíssimo maior do que a falta de testes).
http://rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf
fonte
Depende da pessoa, bem como da complexidade e forma do código com o qual você está trabalhando.
Para mim, na maioria dos projetos, escrever testes de unidade significa que eu concluo o trabalho cerca de 25% mais rápido. Sim, incluindo o tempo para escrever os testes.
Porque o fato é que o software não é feito quando você escreve o código. Isso é feito quando você o envia ao cliente e ele fica feliz com isso. Os testes de unidade são, de longe, a maneira mais eficiente que conheço para capturar a maioria dos bugs, isolar a maioria dos bugs para depuração e ganhar confiança de que o código é bom. Você tem que fazer essas coisas de qualquer maneira , então faça-as bem.
fonte
O problema piora à medida que a idade do projeto aumenta: porque sempre que você adiciona novas funcionalidades e / ou refatora a implementação existente, deve testar novamente o que foi testado anteriormente para garantir que ele ainda funcione. Portanto, para um projeto de longa duração (vários anos), pode ser necessário não apenas testar a funcionalidade, mas testá-la novamente 100 vezes. Por esse motivo, você pode se beneficiar de ter testes automatizados . No entanto, a IMO é boa o suficiente (ou até melhor) se forem testes de sistema automatizados, em vez de testes de unidade automatizados.
Um segundo problema é que os erros podem ser mais difíceis de encontrar e corrigir se não forem detectados mais cedo. Por exemplo, se houver um erro no sistema e eu sei que ele estava funcionando perfeitamente antes que você fizesse a última alteração, concentrei minha atenção nas últimas alterações para ver como ele pode ter introduzido o erro. Mas se eu não souber que o sistema estava funcionando antes de você fazer a última alteração (porque o sistema não foi testado corretamente antes da última alteração), o bug pode estar em qualquer lugar.
O acima se aplica especialmente ao código profundo e menos ao código superficial, por exemplo, adicionando novas páginas da web onde é improvável que novas páginas afetem as páginas existentes.
Na minha experiência, isso seria inaceitável, e você está fazendo a pergunta errada. Em vez de perguntar se os testes tornariam o desenvolvimento mais rápido, você deveria perguntar o que tornaria o desenvolvimento mais livre de bugs.
Uma pergunta melhor pode ser:
O aprendizado é um processo de duas etapas: aprenda a fazê-lo bem o suficiente e, em seguida, aprenda a fazer isso mais rapidamente.
fonte
Alguns aspectos a serem considerados, não mencionados nas outras respostas.
Sumário
Ao iniciar com tdd, é difícil atingir o estado "mais benefício que custo", desde que você esteja em "ambiente de trabalho com restrição de tempo", especialmente se houver "gerentes inteligentes" que dizem para você "se livrar do caro e inútil" testando coisas "
Nota: com "teste de unidade", quero dizer "teste de módulos isolados".
Nota: com "teste de regressão" quero dizer
fonte
Os programadores, como as pessoas que lidam com a maioria das tarefas, subestimam quanto tempo realmente leva para concluí-lo. Com isso em mente, gastar 10 minutos para escrever um teste pode ser visto como o tempo que se passaria escrevendo toneladas de código, quando, na realidade, você gastaria esse tempo criando o mesmo nome de função e parâmetros que você fez durante o teste . Este é um cenário TDD.
Não escrever testes é como ter um cartão de crédito; nós tendemos a gastar mais ou escrever mais código. Mais código tem mais erros.
Em vez de decidir ter uma cobertura total de código ou nenhuma, sugiro focar na parte crítica e complicada do seu aplicativo e fazer testes lá. Em um aplicativo bancário, esse pode ser o cálculo de juros. Uma ferramenta de diagnóstico de mecanismo pode ter protocolos de calibração complexos. Se você está trabalhando em um projeto, provavelmente sabe o que é e onde estão os erros.
Comece devagar. Crie alguma fluência antes de julgar. Você sempre pode parar.
fonte
Há uma longa história do quadro de programadores promovendo o TDD e outras metodologias de teste. Não vou lembrar de seus argumentos e concordar com eles, mas há outras coisas a serem consideradas que devem ser sutis:
Eu diria que o teste é bom, mas certifique-se de testar cedo e onde está o ganho.
fonte
mainTest()
que chama todos os seus módulos de teste não é tão difícil assim.Um benefício muitas vezes esquecido do TDD é que os testes atuam como uma salvaguarda para garantir que você não introduza novos bugs ao fazer uma alteração.
A abordagem TDD é, sem dúvida, mais demorada inicialmente, mas o ponto principal é que você escreverá menos código, o que significa menos coisas para dar errado. Todos os sinos e assobios que você costuma incluir normalmente não serão incluídos na base de código.
Há uma cena no filme Swordfish em que, se a memória serve, um hacker está tendo que trabalhar com uma arma na cabeça e estar erm ... caso contrário, distraído. O ponto é que é muito mais fácil trabalhar quando seu espaço de cabeçalho está no código e você tem tempo do seu lado, em vez de meses na fila com um cliente gritando com você e outras prioridades sendo reduzidas.
Os desenvolvedores entendem que corrigir bugs mais tarde é mais caro, mas vire isso de cabeça para baixo. Se você pudesse receber US $ 500 por dia para codificar como codificá-lo agora ou US $ 1000 se escrevesse de maneira TDD, morderia a mão da pessoa que fez a segunda oferta. Quanto mais cedo você parar de ver os testes como uma tarefa árdua e como uma economia de dinheiro, melhor será.
fonte
Posso me relacionar com a sua experiência - nossa base de código quase não tinha testes e era praticamente não testável. Demorou literalmente eras para desenvolver algo e a correção de erros de produção levou um tempo precioso a partir de novos recursos.
Para uma reescrita parcial, prometi escrever testes para todas as funcionalidades principais. No começo, demorou consideravelmente mais e minha produtividade sofreu visivelmente, mas depois minha produtividade foi melhor do que nunca.
Parte dessa melhoria foi que eu tinha menos erros de produção, o que, por sua vez, levou a menos interrupções -> tive um foco melhor a qualquer momento.
Além disso, a capacidade de testar E depurar código isoladamente realmente vale a pena - um conjunto de testes é muito superior a um sistema que não pode ser depurado, exceto com a configuração manual, por exemplo, iniciando o aplicativo e navegando até a tela e fazer algo ... talvez algumas dezenas de vezes
Mas observe que há uma queda de produtividade no início; portanto, comece a aprender testes em algum projeto em que a pressão do tempo ainda não seja insana. Além disso, tente iniciá-lo em um projeto greenfield, o código legado para testes de unidade é muito difícil e ajuda quando você sabe como é um bom conjunto de testes.
fonte
Apenas para complementar as respostas anteriores: lembre-se de que o teste não é um objetivo em si. O objetivo de fazer testes é que seu aplicativo se comporte conforme o esperado na evolução, em contextos inesperados, etc.
Portanto, escrever testes não significa provar todos os comportamentos de todos os pontos de extremidade de uma entidade. Este é um erro comum. Muitos desenvolvedores acham que precisam testar todas as funções / objetos / métodos / propriedades / etc. Isso leva a uma alta carga de trabalho e a vários códigos e testes irrelevantes. Essa abordagem é comum em grandes projetos, onde a maioria dos desenvolvedores não está ciente do comportamento holístico, mas pode apenas ver seu domínio de interação.
A abordagem correta ao lidar com recursos e testes esparsos é bastante óbvia e de senso comum, mas não é formalizada: invista os recursos de desenvolvimento de testes primeiro em funcionalidades de alto nível e desça gradualmente em especificidades . Isso significa que, em algum momento, como desenvolvedor solitário, você não focaria apenas no teste de unidade, mas também no funcional / integração / etc. testando e dependendo dos recursos de tempo, gradualmente nas principais funções unitárias, como você planejaria e consideraria. Os testes de alto nível fornecerão as informações necessárias para lidar com os testes unitários / de baixo nível e planejar sua estratégia de desenvolvimento de testes de acordo com os recursos que você possui.
Por exemplo, você gostaria de testar uma cadeia de processamento primeiro como uma caixa preta. Se você achar que algum membro da cadeia falhar devido ao comportamento não considerar uma condição extrema, escreva os testes que garantem a funcionalidade não apenas nesse membro, mas também em outros. Então você entrega. Para o próximo ciclo, você detecta que às vezes a rede falha. Então, você escreve testes que abordam esse problema nos módulos que podem ser vulneráveis. E assim por diante.
fonte