Quaisquer ferramentas / sugestões sobre como refutar o argumento de qualidade da cobertura de código

11

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.

MickJ
fonte
4
Ninguém em qualquer lugar sugere encontrar 100% de cobertura de código, o que é realmente uma tarefa tola.
Jimmy Hoffa
1
Obrigado. E eu já sei e reconheço isso. E também as pessoas tendem a associar 100% de cobertura de código a 100% de cobertura de declaração (ou linha) normalmente. Também não pude resistir - Jimmy, eles estavam procurando por você em todo o lugar.
MickJ
3
"então a equipe reagiria criando rapidamente testes de baixa qualidade e, portanto, perdendo tempo, sem acrescentar qualidade significativa" - ótima equipe!
Piotr Perak
Ok, talvez eu tenha projetado 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.
MickJ
1
@ JimmyHoffa - o software crítico de espaço geralmente requer 100% de cobertura de código.
Mouviciel

Respostas:

9

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.

Ampt
fonte
+1 para a sugestão de que escrever testes primeiro melhora a qualidade dos testes, portanto, uma combinação de Teste primeiro com Cobertura de código é definitivamente útil.
MickJ
Sim, eu sempre achei que, se você escrever testes depois de desenvolver o código, você só testará o que sabe que seu código passará ou você escreverá os testes de uma maneira que complemente a implementação, o que realmente não ajuda ninguém. Se você escrever seus testes independentemente do código, concentre-se no que o código deve fazer e não no que ele faz .
Ampt
Obrigado @Ampt. Além de reforçar o processo com TDD, existem ferramentas de cobertura de código que você recomenda, que atendem a mais critérios de cobertura de maneira mais exaustiva, ajudando a validar a qualidade dos testes escritos, pelo menos até certo ponto?
MickJ
Talvez eu esteja entendendo você incorretamente, mas você está sugerindo que ferramentas diferentes fornecerão uma cobertura diferente para seus testes? Sempre foi minha experiência que as ferramentas de cobertura apenas assistem aos testes executados e registram quais linhas de código são executadas. As ferramentas de comutação não devem ter impacto na cobertura, pois o número de linhas executadas permanece o mesmo. Eu ficaria desconfiado de uma ferramenta que oferece mais cobertura para o mesmo teste. Dito isto, não acho que atingir cada linha de código seja uma boa avaliação da qualidade do teste , pois é minuciosa . Bons testes vêm de bons requisitos.
Ampt
Obrigado. O que você está se referindo é Statement Coverage(ou linhas de código executadas). Eu estava procurando mais do que apenas declarações ou cobertura de linha, entrando mais em multiple coverage criterianí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.
MickJ
6

Primeiro, as pessoas fazem defensor cobertura de 100%:

A maioria dos desenvolvedores vê ... "100% de cobertura de declaração" como adequada. Este é um bom começo, mas dificilmente suficiente. Um ID de padrão de cobertura melhor para atender ao chamado "100% de cobertura da filial" ...

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:

  • JaCoCo e o plugin EclEmma associado EclEmma para medir a cobertura do código.
  • Scripts Ant para construção, teste e geração de relatórios automatizados.
  • Jenkins para construções contínuas - qualquer alteração no controle de origem aciona uma construção automática
  • JaCoCo Plugin for Jenkins - captura métricas de cobertura para cada build e representa graficamente as tendências. Também permite definições de limites de cobertura por projeto que afetam a saúde da construção.
  • Bugzilla para rastrear bugs.

Depois de colocar isso (ou algo semelhante), você pode começar a examinar seus próprios dados mais de perto:

  • são encontrados mais erros em projetos mal cobertos?
  • são encontrados mais erros em classes / métodos mal cobertos?
  • etc.

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.

Nathan Gerhart
fonte
Eu realmente gosto desta resposta. Obrigado pelas sugestões de ferramentas e, mais importante, gosto da ideia da abordagem com suporte de dados para justificar a cobertura do código. Embora eu costumo levar a palavra da equipe no valor dela e não questione isso de qualquer maneira. Isso pode me ajudar a construir um caso mais sólido para a nossa experiência até agora. Obrigado!
MickJ
4

O argumento dessas pessoas é: a equipe reagiria criando rapidamente testes de baixa qualidade e, assim, perdendo tempo sem acrescentar qualidade significativa.

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?

Steven A. Lowe
fonte
Como eles sabem que a funcionalidade do código é o resultado final, assim: testes, documentação, comentários, revisões etc. podem ser sacrificados sem consequências imediatas; embora eu concorde, é um mau sinal.
Jeffo
Ok, talvez eu tenha projetado 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.
MickJ
3

Ok, talvez eu tenha projetado um pouco demais, mas você entendeu. O problema é definir processos / políticas em geral em todas as equipes de maneira homogênea / consistente.

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:

  1. dev: ei, olha - eu adicionei métricas de cobertura de código ao nosso painel, não é ótimo?
  2. gerente: claro, vamos adicionar metas obrigatórias e conformidade àquelas
  3. dev: não importa, a cobertura do código é estúpida e inútil, vamos deixar para lá
ptyx
fonte
1
+1 Eu já vi isso muitas vezes para discordar. Eu sou o meu caso, embora a conversa seja um pouco dessa maneira. dev: ei, olha - eu adicionei métricas de cobertura de código ao nosso painel, não é ótimo? manager: claro, tudo o que vocês acham que melhora a qualidade é ótimo. Gerentes Chefe do chefe: acho que precisamos ter um processo entre as equipes. Eu acho que a cobertura do código é inútil, a menos que possamos garantir o valor do custo gasto.
MickJ
2

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.

Telastyn
fonte
+1 Boas sugestões, eu particularmente gosto dos Blocos Cobertos / nº de testes e análises de código. Embora já façamos revisões de código, seria útil enfatizar a importância de revisar os próprios testes mais de perto.
MickJ
2

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:

  • Faça testes de unidade com 100% de cobertura de código e você obterá melhor qualidade de código.
  • Aplique o TDD sistematicamente e você obterá um design melhor.
  • Faça programação emparelhada e você melhorará a qualidade do código e reduzirá o tempo de desenvolvimento.

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:

  • Os testes de unidade detectam muitos erros e a cobertura do código indica quais partes do código são testadas, mas testar coisas triviais é inútil. Por exemplo, se ao clicar em um botão, a caixa de diálogo correspondente é aberta, toda a lógica que envia o evento do botão para o componente que abre a caixa de diálogo pode ser testada por um simples teste manual (clique no botão): compensa para a unidade testar essa lógica?
  • Embora o TDD seja uma boa ferramenta de design, ele não funciona bem se o desenvolvedor tiver um entendimento ruim do domínio do problema (veja, por exemplo, este famoso post ).
  • A programação em pares é eficaz se dois desenvolvedores puderem trabalhar juntos, caso contrário, é um desastre. Além disso, desenvolvedores experientes podem preferir discutir brevemente as questões mais importantes e depois codificar separadamente: passar muitas horas discutindo muitos detalhes que eles já sabem que podem ser entediantes e uma grande perda de tempo.

Voltando à cobertura do código.

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.

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.

O argumento dessas pessoas é - então a equipe reagiria criando rapidamente testes de baixa qualidade e, assim, perdendo tempo sem acrescentar qualidade significativa.

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.

como você aloca tempo garantido sem ter nenhuma medida

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.

Giorgio
fonte
Tudo verdade e eu já estou de acordo. Se você notar, eu não aceito 100% de cobertura de código. Trata-se de melhorar seu valor usando técnicas, ferramentas e processos de bettet. Também ajuda a entender completamente os critérios de cobertura do código (a maioria assume que seja linha / instrução). +1 para sua excelente postagem.
MickJ
2

"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.

Xris - Jardineiro Flatbush
fonte
1

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.

ozz
fonte
2
Pontos que não falam tendem a ser discutíveis . (Eu apenas gosto do jogo de palavras lá - minha ortografia é frequentemente corrigida).
1

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á.

adambender
fonte
Obrigado pela ótima sugestão de usar a complexidade ciclomática para escolher o código que merece cobertura e o link Crap4J. Eu também encontrei um grande artigo falando sobre apertando grandiosidade de crap4j na cobertura - schneide.wordpress.com/2010/09/27/...
MickJ
0

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.

Michael Brown
fonte