Acho os testes muito mais difíceis e difíceis de escrever do que o código real que eles estão testando. Não é incomum para mim gastar mais tempo escrevendo o teste do que o código que está testando.
Isso é normal ou estou fazendo algo errado?
As perguntas “ O teste de unidade ou o desenvolvimento orientado a testes vale a pena? ”,“ Estamos gastando mais tempo implementando testes funcionais do que implementando o próprio sistema, isso é normal? ”E suas respostas são mais sobre se vale a pena testar (como em" devemos pular os testes de escrita? "). Embora eu esteja convencido de que os testes são importantes, estou me perguntando se passo mais tempo em testes do que o código real é normal ou se sou apenas eu.
A julgar pelo número de visualizações, respostas e votos positivos da minha pergunta recebida, só posso assumir que é uma preocupação legítima que não é abordada em nenhuma outra pergunta no site.
fonte
Respostas:
Lembro-me de um curso de engenharia de software que um gasta ~ 10% do tempo de desenvolvimento escrevendo um novo código e os outros 90% são depuração, teste e documentação.
Como os testes de unidade capturam a depuração e o esforço de teste em código (potencialmente automatizado), faria sentido que mais esforço fosse neles; o tempo real gasto não deve ser muito maior do que a depuração e o teste que seria necessário sem a gravação dos testes.
Finalmente, os testes também devem servir como documentação! Deve-se escrever testes de unidade da maneira que o código se destina a ser usado; ou seja, os testes (e o uso) devem ser simples, coloque as coisas complicadas na implementação.
Se for difícil escrever seus testes, o código que eles testam provavelmente será difícil de usar!
fonte
Isto é.
Mesmo se você fizer apenas testes de unidade, não é incomum ter mais código nos testes do que o código realmente testado. Não há nada de errado com isso.
Considere um código simples:
Quais seriam os testes? Existem pelo menos quatro casos simples para testar aqui:
O nome da pessoa é
null
. A exceção é realmente lançada? São pelo menos três linhas de código de teste para escrever.O nome da pessoa é
"Jeff"
. Nós recebemos uma"Hello, Jeff!"
resposta? São quatro linhas de código de teste.O nome da pessoa é uma sequência vazia. Que resultado esperamos? Qual é a saída real? Pergunta secundária: corresponde aos requisitos funcionais? Isso significa outras quatro linhas de código para o teste de unidade.
O nome da pessoa é curto o suficiente para uma sequência, mas muito longo para ser combinado com
"Hello, "
o ponto de exclamação. O que acontece?Isso requer muito código de teste. Além disso, as partes mais elementares do código geralmente exigem código de configuração que inicializa os objetos necessários para o código em teste, o que também leva a escrever stubs e zombarias, etc.
Se a proporção for muito grande, nesse caso, você pode verificar algumas coisas:
Existe duplicação de código nos testes? O fato de ser um código de teste não significa que o código deve ser duplicado (cópia-colado) entre testes semelhantes: essa duplicação dificultará a manutenção desses testes.
Existem testes redundantes? Como regra geral, se você remover um teste de unidade, a cobertura da filial deverá diminuir. Caso contrário, isso pode indicar que o teste não é necessário, pois os caminhos já estão cobertos por outros testes.
Você está testando apenas o código que deve testar? Não é esperado que você teste a estrutura subjacente das bibliotecas de terceiros, mas exclusivamente o código do próprio projeto.
Com testes de fumaça, testes de sistema e integração, testes funcionais e de aceitação e testes de estresse e carga, você adiciona ainda mais código de teste, portanto, não é de se preocupar que você tenha quatro ou cinco LOC de testes para cada LOC do código real.
Uma observação sobre TDD
Se você estiver preocupado com o tempo que leva para testar seu código, pode ser que você esteja fazendo errado, ou seja, primeiro o código, testes depois. Nesse caso, o TDD pode ajudar incentivando você a trabalhar em iterações de 15 a 45 segundos, alternando entre código e testes. De acordo com os defensores do TDD, ele acelera o processo de desenvolvimento, reduzindo o número de testes que você precisa fazer e, mais importante, a quantidade de código comercial a ser escrito e especialmente reescrito para teste.
¹ Deixe n ser o comprimento máximo de uma cadeia de caracteres . Podemos chamar
SayHello
e passar por referência uma cadeia de comprimento n -1 que deve funcionar perfeitamente. Agora, naConsole.WriteLine
etapa, a formatação deve terminar com uma sequência de comprimento n + 8, que resultará em uma exceção. Possivelmente, devido aos limites de memória, mesmo uma string contendo n / 2 caracteres levará a uma exceção. A pergunta que se deve fazer é se esse quarto teste é um teste de unidade (parece um, mas pode ter um impacto muito maior em termos de recursos em comparação com os testes de unidade médios) e se ele testa o código real ou a estrutura subjacente.fonte
personName
ajustes em astring
, mas o valor depersonName
mais os valores concatenados excedemstring
.As a rule of thumb, if you remove a unit test, the branch coverage should decrease.
Se eu escrever todos os quatro testes mencionados acima e remover o terceiro teste, a cobertura diminuirá?Eu acho que é importante distinguir entre dois tipos de estratégias de teste: teste de unidade e teste de integração / aceitação.
Embora o teste de unidade seja necessário em alguns casos, muitas vezes é irremediavelmente superado. Isso é exacerbado por métricas sem sentido impostas aos desenvolvedores, como "100% de cobertura". http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf fornece um argumento convincente para isso. Considere os seguintes problemas com testes de unidade agressivos:
Os testes de integração / aceitação, por outro lado, são uma parte extremamente importante da qualidade do software e, na minha experiência, você deve gastar uma quantidade significativa de tempo para corrigi-los.
Muitas lojas consumiram o kool-aid TDD, mas, como mostra o link acima, vários estudos mostram que seu benefício é inconclusivo.
fonte
.equals()
métodos longos gerados pelo Eclipse". Eu escrevi um equipamento de teste paraequals()
ecompareTo()
github.com/GlenKPeterson/TestUtils Quase todas as implementações que eu já testei estavam ausentes. Como você usa coleções seequals()
ehashCode()
não funcionam em conjunto de forma correcta e eficiente? Estou torcendo novamente pelo resto da sua resposta e votei-a novamente. Eu até concordo que alguns métodos equals () gerados automaticamente podem não precisar de testes, mas eu tive tantos bugs com implementações ruins que isso me deixa nervoso.Não pode ser generalizado.
Se eu precisar implementar uma fórmula ou algoritmo a partir de renderização com base física, pode muito bem ser que eu passe 10 horas em testes de unidade paranóicos, pois sei que o menor bug ou imprecisão pode levar a erros quase impossíveis de diagnosticar, meses depois .
Se eu apenas quiser agrupar logicamente algumas linhas de código e atribuir um nome a ele, usado apenas no escopo do arquivo, talvez não seja possível testá-lo (se você insistir em escrever testes para todas as funções, sem exceção, os programadores poderão recuar para escrever o menor número possível de funções).
fonte
Sim, é normal se você estiver falando sobre TDDing. Quando você realiza testes automatizados, protege o comportamento desejado do seu código. Ao escrever seus testes primeiro, você determina se o código existente já possui o comportamento desejado.
Isso significa que:
(Isso não leva em consideração a refatoração de código, que visa gastar menos tempo escrevendo o código subsequente. É equilibrado pela refatoração de teste, que visa gastar menos tempo escrevendo testes subsequentes.)
Sim também se você estiver falando sobre escrever testes após o fato, estará gastando mais tempo:
Então você gasta realmente escrevendo código.
Então, sim, é uma medida esperada.
fonte
Acho que é a parte mais importante.
O teste de unidade nem sempre é sobre "ver se funciona corretamente", é sobre aprender. Depois de testar algo o suficiente, ele fica "codificado" no cérebro e, eventualmente, você diminui o tempo de teste da unidade e pode começar a escrever classes e métodos inteiros sem testar nada até terminar.
É por isso que uma das outras respostas nesta página menciona que, em um "curso", eles fizeram 90% dos testes, porque todos precisavam aprender as advertências de seus objetivos.
O teste de unidade não é apenas um uso muito valioso do seu tempo, pois literalmente aprimora suas habilidades, é uma boa maneira de revisar seu próprio código novamente e encontrar um erro lógico ao longo do caminho.
fonte
Pode ser para muitas pessoas, mas depende.
Se você estiver escrevendo os testes primeiro (TDD), poderá estar enfrentando alguma sobreposição no tempo gasto escrevendo o teste, na verdade, é útil escrever o código. Considerar:
Ao escrever testes depois de escrever o código, você pode descobrir que seu código não é facilmente testável; portanto, escrever testes é mais difícil / leva mais tempo.
A maioria dos programadores está escrevendo código há muito mais tempo que os testes, portanto, espero que a maioria deles não seja tão fluente. Além disso, você adiciona o tempo necessário para entender e utilizar sua estrutura de teste.
Acho que precisamos mudar nossa mentalidade sobre quanto tempo leva para codificar e como o teste de unidade está envolvido. Nunca olhe para ele a curto prazo e nunca compare o tempo total para fornecer um recurso específico, porque você deve considerar não apenas que está escrevendo um código melhor / menos com erros, mas um código que é mais fácil de alterar e ainda o torna melhor / menos buggy.
Em algum momento, todos somos capazes de escrever código tão bom, então algumas das ferramentas e técnicas podem oferecer muito apenas para melhorar nossas habilidades. Não é como se eu pudesse construir uma casa se tivesse apenas uma serra guiada a laser.
fonte
Sim. Com algumas ressalvas.
Antes de tudo, é "normal" no sentido de que a maioria das grandes lojas funciona dessa maneira, portanto, mesmo que essa maneira tenha sido completamente mal orientada e burra, ainda assim, o fato de a maioria das grandes lojas funcionar dessa maneira a torna "normal".
Com isso, não pretendo sugerir que testá-lo esteja errado. Eu trabalhei em ambientes sem teste e em ambientes com teste obsessivo-compulsivo, e ainda posso lhe dizer que mesmo o teste obsessivo-compulsivo foi melhor do que nenhum teste.
E eu ainda não faço TDD (quem sabe, eu posso no futuro), mas faço a grande maioria dos meus ciclos de edição, execução e depuração executando os testes, não o aplicativo real, então, naturalmente, trabalho muito nos meus testes, para evitar ao máximo a execução do aplicativo real.
No entanto, esteja ciente de que há perigos em testes excessivos e, especificamente, na quantidade de tempo gasto na manutenção dos testes. (Estou escrevendo principalmente esta resposta para apontar isso especificamente.)
No prefácio de The Art of Unit Testing (Manning, 2009), de Roy Osherove , o autor admite ter participado de um projeto que falhou em grande parte devido à enorme carga de desenvolvimento imposta por testes de unidade mal projetados que tiveram que ser mantidos durante todo o período. duração do esforço de desenvolvimento. Portanto, se você passar muito tempo sem fazer nada além de manter seus testes, isso não significa necessariamente que você está no caminho certo, porque é "normal". Seu esforço de desenvolvimento pode ter entrado em um modo não íntegro, onde pode ser necessário repensar radicalmente sua metodologia de teste para salvar o projeto.
fonte
fonte