Agora eu sei que as pessoas poderiam considerar essa pergunta duplicada ou perguntada várias vezes; nesse caso, eu apreciaria um link para perguntas relevantes com resposta à minha pergunta.
Recentemente, estive em desacordo com algumas pessoas sobre a cobertura de código. Eu tenho um grupo de pessoas que deseja que nossa equipe abandone completamente a cobertura de código com base no argumento de que 100% de cobertura não significa testes de boa qualidade e, portanto, código de boa qualidade.
Consegui recuar vendendo o argumento de que o Code Coverage me diz o que não foi testado com certeza e nos ajuda a focar nessas áreas.
(O exposto acima foi discutido de maneira semelhante em outras questões SO, como esta - /programming/695811/pitfalls-of-code-coverage )
O argumento dessas pessoas é - então a equipe reagiria criando rapidamente testes de baixa qualidade e, assim, perdendo tempo sem acrescentar qualidade significativa.
Embora eu compreenda o ponto de vista deles, estou procurando uma maneira de apresentar um caso mais robusto para a cobertura de código, introduzindo ferramentas / estruturas mais robustas que atendam a mais critérios de cobertura (Functional, Statement,Decision, Branch, Condition, State, LCSAJ, path, jump path, entry/exit, Loop, Parameter Value etc)
.
O que estou procurando é sugerir uma combinação dessas ferramentas e práticas / processos de cobertura de código para acompanhá-los, o que pode me ajudar a combater esses argumentos enquanto me sinto à vontade com minha recomendação.
Também gostaria de receber quaisquer comentários / sugestões que acompanhem, com base na sua experiência / conhecimento sobre como combater esse argumento, porque, embora subjetiva, a cobertura do código ajudou minha equipe a ter mais consciência da qualidade do código e do valor dos testes.
Edit: Para reduzir qualquer confusão sobre minha compreensão da fraqueza da cobertura típica de código, quero ressaltar que não estou me referindo a Statement Coverage
(ou linhas de código executadas) ferramentas (há muitas). De fato, aqui está um bom artigo sobre tudo o que está errado: http://www.bullseye.com/statementCoverage.html
Eu estava procurando mais do que apenas cobertura de declaração ou linha, entrando mais em vários critérios e níveis de cobertura.
Veja: http://en.wikipedia.org/wiki/Code_coverage#Coverage_criteria
A ideia é que, se uma ferramenta pode nos dizer nossa cobertura com base em vários critérios, isso se torna uma avaliação automatizada razoável da qualidade do teste. Não estou tentando dizer que a cobertura da linha é uma boa avaliação. Na verdade, essa é a premissa da minha pergunta.
Edit:
Ok, talvez eu o projetei um pouco demais, mas você entendeu. O problema é definir processos / políticas em geral em todas as equipes de maneira homogênea / consistente. E o medo é geral de que como você garante a qualidade dos testes, como você aloca tempo garantido sem ter nenhuma medida para isso. Assim, eu gosto de ter um recurso mensurável que, quando feito em backup com processos apropriados e as ferramentas certas, nos permita melhorar a qualidade do código, sabendo que o tempo não está sendo gasto com força em processos desnecessários.
EDIT: Até agora, o que tenho das respostas:
- As revisões de código devem abranger testes para garantir a qualidade dos testes
- A estratégia Test First ajuda a evitar testes escritos após o fato para simplesmente aumentar a cobertura%
- Explorando ferramentas alternativas que cobrem critérios de teste que não sejam simplesmente Declaração / Linha
- A análise do código coberto / número de bugs encontrados ajudaria a apreciar a importância da cobertura e faria uma melhor situação
- O mais importante é confiar nas informações da equipe para fazer a coisa certa e lutar por suas crenças.
- Blocos cobertos / nº de testes - discutível, mas possui algum valor
Obrigado pelas respostas impressionantes até agora. Eu realmente aprecio eles. Essa discussão é melhor do que horas de brainstorm com os poderes que existem.
fonte
Respostas:
Na minha experiência, a cobertura do código é tão útil quanto você . Se você escrever bons testes que cobrem todos os seus casos, passar nesses testes significa que você atendeu aos seus requisitos. Na verdade, essa é a idéia exata que o Test Driven Development usa. Você escreve os testes antes do código sem saber nada sobre a implementação (Às vezes, isso significa que outra equipe escreve inteiramente os testes). Esses testes são configurados para verificar se o produto final faz tudo o que suas especificações dizem que foi feito e, em seguida, você escreve o código mínimo para passar nesses testes.
O problema aqui, obviamente, é que, se seus testes não forem fortes o suficiente, você perderá casos extremos ou problemas imprevistos e escreverá um código que não atende verdadeiramente às suas especificações. Se você está realmente decidido a usar testes para verificar seu código, escrever bons testes é uma necessidade absoluta ou você está realmente desperdiçando seu tempo.
Queria editar a resposta aqui, pois percebi que ela realmente não respondeu à sua pergunta. Eu examinaria esse artigo da wiki para ver alguns benefícios declarados do TDD. Realmente se resume à forma como sua organização funciona melhor, mas o TDD é definitivamente algo em uso no setor.
fonte
Statement Coverage
(ou linhas de código executadas). Eu estava procurando mais do que apenas declarações ou cobertura de linha, entrando mais emmultiple coverage criteria
níveis e níveis. Consulte: en.wikipedia.org/wiki/Code_coverage#Coverage_criteria e en.wikipedia.org/wiki/Linear_Code_Sequence_and_Jump . A ideia é que, se uma ferramenta pode nos dizer nossa cobertura com base em vários critérios, isso se torna uma avaliação automatizada razoável da qualidade do teste. Não estou tentando dizer que a cobertura da linha é uma boa avaliação. Na verdade, essa é a premissa da minha pergunta.Primeiro, as pessoas fazem defensor cobertura de 100%:
Steve McConnell, Code Complete , Capítulo 22: Teste do Desenvolvedor.
Como você e outras pessoas mencionaram, a cobertura do código apenas por uma questão de cobertura provavelmente não realizará muito. Mas se você não pode executar uma linha de código, por que está escrita?
Eu sugiro resolver o argumento reunindo e analisando dados em seus próprios projetos.
Para coletar os dados, eu pessoalmente uso as seguintes ferramentas:
Depois de colocar isso (ou algo semelhante), você pode começar a examinar seus próprios dados mais de perto:
Eu esperaria que os seus dados irá apoiar a sua posição sobre a cobertura de código; essa certamente foi minha experiência. Se isso não acontecer, no entanto, talvez sua organização possa ter sucesso com padrões de cobertura de código mais baixos do que você gostaria. Ou talvez seus testes não sejam muito bons. Espera-se que a tarefa concentre os esforços na produção de software com menos defeitos, independentemente da resolução do desacordo na cobertura do código.
fonte
Esta é uma questão de confiança , não de ferramentas .
Pergunte-lhes por que, se eles realmente acreditam nessa afirmação, confiariam na equipe para escrever algum código?
fonte
Eu acho que esse é o problema. Os desenvolvedores não se importam (e geralmente por excelentes razões) com políticas consistentes ou globais e querem a liberdade de fazer o que acham certo, em vez de cumprir as políticas corporativas.
O que é razoável, a menos que você prove que os processos e medidas globais têm valor e um efeito positivo na qualidade e velocidade do desenvolvimento.
Linha do tempo usual:
fonte
Na minha experiência, há algumas coisas a combinar com a cobertura do código para fazer a métrica valer a pena:
Revisões de código
Se você pode enviar testes ruins de volta ao desenvolvedor, isso pode ajudar a limitar o número de testes ruins que estão fornecendo essa cobertura sem sentido.
Rastreamento de bugs
Se você possui várias coberturas de código em um módulo, mas ainda possui muitos / erros graves nessa área, isso pode indicar um problema em que o desenvolvedor precisa melhorar com seus testes.
Pragmatismo
Ninguém vai chegar a 100% com bons testes em código não trivial. Se você, como líder da equipe, examinar a cobertura do código, mas em vez de dizer "precisamos chegar a N%!" você identifica lacunas e pede às pessoas que "melhorem a cobertura no módulo X" que atinge seu objetivo sem oferecer às pessoas a oportunidade de jogar o sistema.
Blocos Cobertos / Nº de Testes
A maioria das ferramentas de cobertura de código lista blocos cobertos versus blocos não cobertos. Combinar isso com o número de testes reais permite obter uma métrica indicando como os testes são "amplos", indicando testes ruins ou design acoplado. Isso é mais útil como um delta de um sprint para outro, mas a idéia é a mesma: combine a cobertura do código com outras métricas para obter mais informações.
fonte
Aqui estão meus 2 centavos.
Há muitas práticas que receberam muita atenção recentemente porque podem trazer benefícios ao desenvolvimento de software. No entanto, alguns desenvolvedores aplicam essas práticas cegamente: eles estão convencidos de que aplicar uma metodologia é como executar um algoritmo e que, após executar as etapas corretas, deve-se obter o resultado desejado.
Alguns exemplos:
Penso que o problema básico com as afirmações acima é que humanos não são computadores e escrever software não é como executar um algoritmo.
Portanto, as declarações acima contêm alguma verdade, mas simplificam demais as coisas, por exemplo:
Voltando à cobertura do código.
Eu acho que você deve julgar caso a caso se vale a pena ter 100% de cobertura para um determinado módulo.
O módulo executa algum cálculo muito importante e complicado? Gostaria de testar todas as linhas de código, mas também escrever testes de unidade significativos (testes de unidade que façam sentido nesse domínio).
O módulo executa alguma tarefa importante, mas simples, como abrir uma janela de ajuda ao clicar em um botão? Um teste manual provavelmente será mais eficaz.
Na minha opinião, eles estão certos: você não pode impor a qualidade do código exigindo apenas 100% de cobertura do código. Adicionar mais ferramentas para calcular a cobertura e fazer estatísticas também não ajudará. Em vez disso, você deve discutir quais partes do código são mais sensíveis e devem ser testadas extensivamente e quais são menos suscetíveis a erros (no sentido de que um erro pode ser descoberto e corrigido com muito mais facilidade sem o uso de testes de unidade).
Se você colocar 100% de cobertura de código nos desenvolvedores, alguns começarão a escrever testes de unidade bobos para cumprir suas obrigações, em vez de tentarem escrever testes sensíveis.
Talvez seja uma ilusão que você possa medir a inteligência e o julgamento humanos. Se você tiver colegas competentes e confiar no julgamento deles, poderá aceitar quando eles disserem "para este módulo, aumentar a cobertura do código trará muito pouco benefício. Portanto, não vamos gastar tempo com ele" ou "para este módulo que precisamos" Para obter o máximo de cobertura possível, precisamos de uma semana extra para implementar testes de unidade sensíveis ".
Então (novamente, esses são meus 2 centavos): não tente encontrar um processo e definir parâmetros como cobertura de código que deve atender a todas as equipes, a todos os projetos e a todos os módulos. Encontrar um processo tão geral é uma ilusão e acredito que, quando você o encontrar, ficará abaixo do ideal.
fonte
"a equipe reagiria criando rapidamente testes de baixa qualidade e, portanto, perdendo tempo, sem adicionar qualidade significativa"
Este é um risco real, não apenas teórico.
O excesso de código por si só é uma métrica disfuncional. Aprendi essa lição da maneira mais difícil. Certa vez, enfatizei isso sem a disponibilidade de métricas ou práticas de balanceamento. Centenas de testes que capturam e mascaram exceções e sem afirmações são uma coisa feia.
"sugestão de uma combinação dessas ferramentas e práticas / processos de cobertura de código para acompanhá-los"
Além de todas as outras sugestões, existe uma técnica de automação que pode avaliar a qualidade dos testes: teste de mutação ( http://en.wikipedia.org/wiki/Mutation_testing ). Para código Java, o PIT ( http://pitest.org/ ) funciona, e é a primeira ferramenta de teste de mutação que encontrei.
Como você observa, a falta de cobertura de código é facilmente identificável como um risco de qualidade de software. Ensino que a cobertura do código é uma condição necessária, mas insuficiente, para a qualidade do software. Temos que adotar uma abordagem de balanced scorecard para gerenciar a qualidade do software.
fonte
A cobertura do código certamente não é prova de bons testes de unidade, pois eles estão corretos.
Mas, a menos que eles possam fornecer uma maneira de provar que todos os testes de unidade são bons (seja qual for a definição de bem que possam surgir), esse é realmente um ponto mudo.
fonte
Sempre achei que a cobertura do código é facilmente suscetível ao efeito Hawthorne . Isso me levou a perguntar "por que temos alguma métrica de software?" e a resposta geralmente é fornecer um entendimento de alto nível do estado atual do projeto, coisas como:
"quão perto estamos de terminar?"
"como está a qualidade deste sistema?"
"quão complicados são esses módulos?"
Infelizmente, nunca haverá uma única métrica que possa dizer o quão bom ou ruim o projeto é, e qualquer tentativa de derivar esse significado de um único número será necessariamente simplificada. Embora as métricas sejam sobre dados, interpretar o que elas significam é uma tarefa muito mais emocional / psicológica e, como tal, provavelmente não pode ser aplicada genericamente em equipes de diferentes composições ou problemas de diferentes domínios.
No caso da cobertura, acho que é frequentemente usado como proxy da qualidade do código, embora seja grosseiro. E o verdadeiro problema é que ele resume um tópico extremamente complicado em um único número inteiro entre 0 e 100, o qual, é claro, será usado para conduzir trabalhos potencialmente inúteis em uma busca sem fim para obter 100% de cobertura. Pessoas como Bob Martin dirão que 100% de cobertura é o único objetivo sério, e eu posso entender por que isso acontece, porque qualquer outra coisa parece arbitrária.
É claro que existem muitas maneiras de obter cobertura que realmente não me ajudam a entender a base de código - por exemplo, é valioso testar toString ()? que tal getters e setters para objetos imutáveis? Uma equipe só tem muito esforço para se candidatar em um horário fixo e esse tempo sempre parece ser menor que o tempo necessário para fazer um trabalho perfeito; portanto, na ausência de um cronograma perfeito, temos que nos contentar com aproximações.
Uma métrica que achei útil para fazer boas aproximações é o Crap4J . Agora está desativado, mas você pode facilmente portar / implementar você mesmo. O Crap4J tenta relacionar a cobertura do código à complexidade ciclomática , implicando que o código mais complicado (ifs, whiles, fors etc.) deve ter uma cobertura de teste mais alta. Para mim, essa idéia simples realmente soou verdadeira. Quero entender onde há risco na minha base de código e um risco realmente importante é a complexidade. Então, usando essa ferramenta, posso avaliar rapidamente o risco da minha base de código. Se for complicado, é melhor aumentar a cobertura. Se não for, não preciso perder tempo tentando obter todas as linhas de código cobertas.
Claro que isso é apenas uma métrica e YMMV. Você precisa dedicar algum tempo para entender se fará sentido para você e se isso dará à sua equipe uma sensação razoavelmente grupal de onde o projeto está.
fonte
Eu não diria que voltar e cobrir o código existente é o melhor caminho a seguir. Eu argumentaria que faz sentido escrever testes de cobertura para qualquer novo código que você escreve e / ou qualquer código que você altera.
Quando forem encontrados erros, escreva um teste que falhe por causa desse erro e corrija-o para que o teste fique verde. Coloque nos comentários do teste para que bug foi escrito.
O objetivo é ter confiança suficiente em seus testes para que você possa fazer alterações sem se preocupar com efeitos colaterais inesperados. Confira Trabalhando efetivamente com o código herdado para obter um bom resumo das abordagens para domesticar o código não testado.
fonte