Você não deve impor a cobertura do código automaticamente.
É como impor o máximo de linhas de código por método: concordado, a maioria dos métodos deve ser menor que, digamos, 20 LOC, mas há casos válidos em que os métodos seriam mais longos que isso.
Da mesma forma, segmentar uma determinada porcentagem de cobertura de código por classe pode levar a conseqüências indesejadas. Por exemplo:
Classes de código padrão ou classes criadas por geradores de código podem não ser testadas. Forçar os desenvolvedores a testá-los não terá nenhum benefício e terá um custo substancial em termos de tempo gasto com isso.
O código simples que manipula partes não importantes do aplicativo não precisa necessariamente ser testado.
Em alguns idiomas, algum código não pode ser testado. Eu tive esse caso em C # com métodos anônimos em uma biblioteca onde eu realmente queria ter 100% de cobertura de código. Esses casos podem ser desmoralizantes para os desenvolvedores.
Mais importante, a cobertura do código deve ser proporcional a dois aspectos do código: quão crítico e quão complicado é :
Um pedaço de código com uma lógica complicada, que faz parte do principal recurso de um aplicativo, seria melhor testado cuidadosamente, porque falhas ou regressões podem ter consequências importantes.
Um código simples que lida com um recurso que ninguém usa pode ter testes básicos que abrangem apenas casos básicos.
Obviamente, você ainda pode usar a cobertura de código como uma medida , especialmente para comparar como equipes diferentes obtêm cobertura de código: pode haver equipes menos disciplinadas e mais relutantes quando se trata de testar. Nesses casos, convém combinar essa métrica com outras, como o número de bugs, o tempo gasto na resolução de bugs ou o número de observações durante as revisões de código.
Você também pode aplicar pelo menos uma cobertura de código, digamos 60% ¹, em projetos individuais onde faz sentido (tenha cuidado para excluir protótipos, código gerado, CRUD, etc.) Possibilitando aos desenvolvedores marcar classes específicas como excluídas da cobertura do código também é bom². Nesse caso, isso pode ser feito sob a forma de uma verificação que falha na compilação se a cobertura do código estiver abaixo do mínimo necessário. Eu faria isso no estágio de construção, não no estágio de confirmação , pois não é esperado que você execute testes de unidade durante o commit .
¹ Eu consideraria 60% como um mínimo razoável, com base na minha base de código: quase todos os projetos ou classes com menos de 60% de cobertura de código são realmente não testados . Isso pode variar muito de um idioma para outro e de uma empresa para outra (em algumas empresas, 0% é um padrão). Certifique-se de discutir com sua equipe o que é normal e o que é alto demais para eles. Talvez eles estejam constantemente atingindo 95% e possam atingir 99% facilmente, ou talvez tenham dificuldade para aumentar sua cobertura de código de 70% para 75%.
² Dado que eventuais abusos serão detectados durante as revisões de código, você não deve ter medo de dar essa possibilidade aos desenvolvedores. Isso é semelhante à possibilidade de excluir algumas partes do código das verificações pelas linhas ou verificadores de estilo. JSLint, StyleCop e Code Analysis são três exemplos em que a exclusão é suportada e é realmente útil sem incentivar o abuso.
Considere o seguinte código:
Não há como criar um caso de teste que alcance esse ramo. No entanto, se esse fosse um software de vôo crítico para a segurança, as pessoas estariam em todo o caso do autor se essa proteção contra o envio de um valor negativo
sqrt
não estivesse presente. Normalmente, o cálculorsq = a*a + b*b
e a extração da raiz quadrada são separados por várias linhas de código. Enquanto isso, um raio cósmico pode ativar o sinalrsq
.De fato, o software de vôo invocou o equivalente a
handle_this_impossible_event()
várias vezes. Geralmente, isso envolve alternar o controle para um computador redundante, desligar normalmente o computador suspeito, reiniciar o computador suspeito e, finalmente, o computador suspeito assumindo a função de backup. Isso é muito melhor do que o computador de vôo principal que está ficando louco.Mesmo em software de vôo, é impossível obter 100% de cobertura de código. As pessoas que afirmam ter conseguido isso têm código trivial ou não têm testes suficientes contra esses eventos impossíveis.
fonte
a
eb
forem números inteiros de 32 bits assinados, muitos valores como 65535 e 65535 ou 40000 e 40000 podem resultarrsq
negativos.0.0
, implicando quea
eb
são algum tipo de ponto flutuante. Com o software de vôo, é imperativo proteger contra a raiz quadrada de um número negativo, mesmo se você souber que o número não pode ser negativo. Os raios cósmicos são pequenas coisas desagradáveis. Um experimento muito recente ( lançado há menos de uma semana ) estudará se um supercomputador na Estação Espacial Internacional pode usar software em vez de hardware para proteger contra raios cósmicos (SEUs, etc.).0.0
.A cobertura do teste é uma métrica útil para a integridade geral do seu projeto. Uma alta cobertura de teste permite que você tome uma decisão informada sobre se o software funcionará conforme o esperado quando implantado; com uma baixa cobertura de teste, o que implica que você está apenas adivinhando. Existem ferramentas para medir a cobertura automaticamente, geralmente funcionam executando o programa em um contexto de depuração ou injetando operações de contabilidade no código executado.
Existem diferentes tipos de testes e diferentes tipos de métricas de cobertura. As métricas de cobertura comuns incluem cobertura de função, cobertura de extrato, cobertura de filial e cobertura de condição, embora haja mais .
Os testes de unidade verificam se a implementação de uma unidade conceitual (módulo, classe, método, ...) está de acordo com sua especificação (em TDD, o teste é a especificação). Unidades sem seus próprios testes de unidade são uma bandeira vermelha, embora possam ser cobertas por testes no estilo de integração.
Os testes de unidade devem implicar cobertura quase total da função - como o teste de unidade exerce toda a interface pública dessa unidade, não deve haver funcionalidade que não seja tocada por esses testes. Se você estiver introduzindo o teste de unidade em uma base de código existente, a cobertura das funções é um indicador aproximado de progresso.
Um teste de unidade deve buscar uma boa cobertura de declaração (75% a 100%). A cobertura da declaração é uma métrica de qualidade para um teste de unidade. A cobertura total nem sempre é possível e você provavelmente usa melhor o seu tempo do que para melhorar a cobertura além de 95%.
A cobertura de filial e condição é mais complicada. Quanto mais complicado ou importante for um código, maiores serão essas métricas. Porém, para código não espetacular, a alta cobertura de declaração tende a ser suficiente (e já implica uma cobertura de filial de pelo menos 50%). Examinar o relatório de cobertura de condições de uma unidade pode ajudar a construir melhores casos de teste.
Os testes de integração verificam se várias unidades podem funcionar corretamente umas com as outras. Os testes de integração podem ser muito úteis sem pontuar alto em qualquer métrica de cobertura. Enquanto os testes de integração geralmente exercem grande parte das interfaces de suas unidades (ou seja, possuem alta cobertura de funções), os internos dessas unidades já foram cobertos pelos testes de unidade.
A execução de testes antes que o código seja mesclado em uma ramificação principal é uma boa idéia. No entanto, o cálculo das métricas de cobertura de teste para todo o programa tende a demorar muito tempo - esse é um bom trabalho para uma construção noturna. Se você puder descobrir como fazer isso, um bom compromisso seria executar apenas testes alterados ou testes de unidade em unidades alteradas em um gancho Git. As falhas no teste não são aceitáveis para nada além de "trabalhos em andamento" - confirma. Se as métricas de cobertura selecionadas caírem abaixo de algum limite (por exemplo, cobertura de declaração abaixo de 80% ou a introdução de novos métodos sem os testes correspondentes), esses problemas devem ser tratados como um aviso, com uma oportunidade para o desenvolvedor corrigir esses possíveis problemas. No entanto, algumas vezes há boas razões para ignorar esses avisos, e os desenvolvedores devem poder fazer isso.
Os testes são bons, mas muitos deles podem ser irritantes. O feedback rápido e relevante pode ajudar a promover a atenção à qualidade, mas você não deseja que isso atrapalhe a produção de valor. Pessoalmente, prefiro executar testes manualmente, pois isso permite um feedback mais rápido da parte em que estou trabalhando. Antes do lançamento, farei um foco na qualidade em que uso análise estática, perfis e ferramentas de cobertura de código para encontrar zonas problemáticas (com algumas dessas etapas fazendo parte de um conjunto de testes de pré-lançamento).
fonte
Ninguém mencionou testes de mutação . A idéia por trás deles é bastante prática e intuitiva.
Eles trabalham modificando o código fonte aleatoriamente (por exemplo, alternando ">" para "<") - daí a mutação - e verificando se essas mudanças aleatórias quebram qualquer teste.
Caso contrário, a) o código em questão pode ser desnecessário ou b) (mais provável) que esse trecho de código não seja coberto por um teste, pois a quebra não será detectada.
fonte
Obviamente, os dados de cobertura de código podem ser obtidos automaticamente, mas nenhuma decisão automática deve ser tomada com base neles, por razões que outros já explicaram. (Muito confuso, muito espaço para erro.)
No entanto, a próxima melhor coisa é ter um processo estabelecido pelo qual o estado atual do projeto em termos de cobertura de código seja regularmente verificado por seres humanos, possivelmente com relatórios diários chegando na caixa de entrada do gerente de projeto.
Em ambientes corporativos, isso é alcançado com as ferramentas de Integração Contínua , como Hudson, Jenkins, etc. Essas ferramentas são configuradas para verificar regularmente todo o projeto no repositório de códigos-fonte, construí-lo, executar os testes e gerar relatórios. Obviamente, eles podem ser configurados para executar os testes no modo de cobertura de código e incluir os resultados nesses relatórios.
O Jetbrains também torna o TeamCity, que me parece um pouco mais leve e adequado para lojas de software menores.
Portanto, o gerente de projeto recebe relatórios regulares de cobertura de código, usa seu próprio bom senso e age como executor, se necessário.
fonte
A cobertura do código pode ser verificada automaticamente, apesar da opinião popular, o conjunto de ferramentas Purify da Rational incluía um recurso de cobertura do código. Ele dependia de instrumentar todas as funções (trabalhava nos binários, atualizando cada função ou chamada com um pouco de código extra) para poder gravar os dados que foram exibidos ao usuário. Tecnologia muito legal, especialmente na época.
No entanto, mesmo quando tentamos realmente obter 100% de cobertura, conseguimos apenas 70% mais ou menos! Portanto, é um exercício inútil.
No entanto, na situação de escrever testes de unidade, acho que 100% da cobertura de testes de unidade é ainda mais inútil. Teste de unidade aqueles métodos que exigem teste de unidade, nem todo getter ou setter! O teste de unidade deve ser sobre a verificação das funções complicadas (ou classes TBH) e não tentar marcar as caixas em algum processo ou ferramenta que mostre boas marcas verdes.
fonte
Eu construí uma ferramenta para isso
https://github.com/exussum12/coverageChecker
Usando
Falhará se menos de 70% do diff for coberto por testes de unidade.
Obtenha o diff por.
Supondo que você ramificou do mestre e se fundirá novamente no mestre
Ignore a flag phpunit no código, é realmente apenas uma verificação de trevo, para que qualquer coisa que possa produzir trevo possa usá-la.
Como outras respostas sugeriram colocar isso a 100% não é uma boa ideia
fonte