Até entendo sua critica de no começo nos acabarmos caindo em armadilhas de se cegar por metricas imprecisas ou até ruins. Isso não só ocorre na hora do desenvolvimento mas também na gestão. Quem nunca viu um PO/PM/Agilista/Scrum Master falar um monte de metricas vazias como story points, troughtput ou pasmem linhas de codigo escritas...
A cobertura teorica de 100% é sim util, sendo a "cobertura teorica" testes unitarios que garantem que todos os use cases possiveis de um objeto, função, script estejam definidos em um teste. Isso seria um ideial que teoricamente nos deixaria livres de bugs deterministicos (ficariamos sujeitos a bugs imprevisiveis como por exemplo bitflip por radiação).
Agora, no mundo real isso não é possivel. Para entender cobertura precisamos entender como a cobertura é calculada pelos frameworks. Geralmente os frameworks calculam isso baseado nas linhas de codigo que vão ser executadas nos testes, claramente isso não é o suficiente para atestar a qualidade de um software, que por mais que alguns frameworks consigam ainda diferenciar desvios condicionais isso não garante que todos os use cases foram testados. De fato como como apontou os testes não só tem uma caracterisca quantitativa mas também uma qualitativa.
Ainda sim uma cobertura de 100% calculada por esses frameworks muito provavelmente em casos concretos é o suficiente para termos uma boa noção do controle de qualidade daquele software. Um software com 80% de cobertura e um com 100% de cobertura provavelmente tem um controle de qualidade melhor que um de 80%.
Mesmo no seu exemplo tu disses que a cobertura é inutil. E isso não é verdade. Existe sim uma utilidade ai. O primeiro teste está ótimo, ele assegura que o objeto instanciado está iniciando como deveria. O segundo teste também é bom, de certa forma até redundante, pois ele atesta que o relogio inicia com 0 e ao executar avancar_hora()
ele incremente +1 no marcador. Isso definitivamente não é "inutil". Podemos dizer que seus testes são incompletos ou de qualidade baixa, mas inutil nunca.
Ta ai uma coisa que temos que entender sobre testes e acredito que seja essa sua intenção a o escrever esse post: Escrever bons testes faz parte da sua skill como programador. Assim como tu precisas aprender desing de código, arquitetura de software, ciclo de vida, aindas deve aprender como escrever bons testes. Testar é muito mais difícil do que a maioria pensa, mas com pratica deliberada podemos melhorar isso como qualquer outro skill da sua carreira.
No fim das contas, eles são importantes sim! Mas sem requisitos claros para orientá-los são literalmente como atirar em alvos imaginários.
Também entendo o que quis dizer aqui mas acho que precisamos explicar melhor. Existem bugs e existem regras de negocio mal especificadas. Eu sei que no coditiano nos costumamos misturar os dois mas existem diferenças:
Um bug é um problema de software, um comportamento não esperado na hora de executar um codigo. Por exemplo um numero que estoura o limite de bits, uma string que entra na função mas era para entrar como inteiro, uma logica mal escrita que não preve certos inputs de dados etc...
Um bug é diferente de um requisito mal especificado. Vamos a o exemplo do relogio, a tua area de produto te manda algo assim:
"Crie um relogio. O relogio deve ter uma funcionalidade que mostra a hora e uma funcionalidade que a o acionar incrementa o mostrador com mais 1 hora."
No caso, o código acima estaria 100% dentro da especificação.
"Ah! Mas sabemos o que é um relogio, o relogio conta as horas e quando chega no 23 o proximo é 0"
Sabemos mesmo??? E se for um outro tipo de relogio, aqui por exemplo chamamos o medidor de gasto de energia eletrica e volume de água de relogio. E se for um relogio no formato americano que a partir do 12 vai para 1? E se o relogio é para contar as horas a partir de um certo momento, identido a o unix time que mostra a data e hora em segundos desde 1970? E se o relogio é lunar.... (kkkk)
Por isso que como realmente precisamos de requisitos claros do que é necessario para escrever os testes e não só os testes como o software produtivo em si. E é por isso que também é seu trabalho como programador é fazer perguntas antes e durante o desenvolvimento!
E vocês colegas desenvolvedores? Continuarão perseguindo unicórnios ou preferem encarar a realidade dura e fria? Se você deseja um software livre de bugs, deixe de lado os testes unitários e abrace a especificação de requisitos.
Deixem suas opniões nos comentários!
Aqui eu acho meio problematico... Não, não deixe os testes unitarios! Os testes unitarios é a sua primeira linha de frente contra os bugs. Os testes unitarios tem certos beneficios que os outros não tem (intergração ou end to end).
- Os testes unitarios são otimos para testar as regras de negocio (use cases), pois eles sofrem menos ruido
- Os testes unitarios são rapidos de executar
- Os testes unitarios deixam claro o objetivo de um pequeno trecho de codigo, serve como documentação.
Testes unitarios é uma bala de prata? Não, obvio que não! Um software sem testes unitarios necessarimente é de baixa qualidade? Não, também não. Mas isso não significa que é uma boa pratica largar eles para fazer outros tipos de testes.
Todos os tipos de testes devem ser adotados na sua aplicação dependendo da complexidade e sensibilidade. Todos os testes cumpre partes que outros testes são dificeis de fazer. Testes e2e são otimos para atestar que todas as tomadas (ligaçoes externas) do software estão bem conectadas, coisas que os testes unitarios não fazem, mas seria muito lento e complicado testar as regras de negocio com ele entre outras coisas.
No fim, em linhas gerais, concordo com o que foi dito pelo colega clacerda
, só acho que a explicação precisava ser um pouco mais profunda. Upvote no post! :D