unit-testing - phpunit tutorial




O que é uma% de cobertura de código razoável para testes de unidade(e por quê)? (20)

Se você exigisse uma porcentagem mínima de cobertura de código para testes de unidade, talvez até como um requisito para se comprometer com um repositório, qual seria?

Por favor, explique como você chegou à sua resposta (desde que tudo o que você fez foi escolher um número, então eu poderia ter feito isso sozinho);


85% seria um bom ponto de partida para os critérios de check-in.

Eu provavelmente escolhi uma variedade de barras mais altas para os critérios de envio - dependendo da criticidade dos subsistemas / componentes que estão sendo testados.


A cobertura de código é ótima, mas a cobertura de funcionalidade é ainda melhor. Eu não acredito em cobrir todas as linhas que escrevo. Mas eu acredito em escrever 100% de cobertura de teste de todas as funcionalidades que eu quero fornecer (mesmo para os recursos extras que eu usei e que não foram discutidos durante as reuniões).

Eu não me importo se eu teria código que não é coberto em testes, mas eu me importaria se eu refatorasse meu código e acabasse tendo um comportamento diferente. Portanto, 100% de cobertura de funcionalidade é meu único alvo.



A resposta aceita faz um bom argumento - não há um único número que faça sentido como um padrão para cada projeto. Existem projetos que simplesmente não precisam desse padrão. Onde a resposta aceita fica aquém, na minha opinião, está em descrever como alguém pode tomar essa decisão para um determinado projeto.

Eu vou tentar fazer isso. Eu não sou especialista em engenharia de testes e ficaria feliz em ver uma resposta mais informada.

Quando definir os requisitos de cobertura de código

Primeiro, por que você quer impor tal padrão em primeiro lugar? Em geral, quando você deseja introduzir confiança empírica em seu processo. O que quero dizer com "confiança empírica"? Bem, a correção real do objetivo. Para a maioria dos softwares, não podemos saber isso em todas as entradas, então nos contentamos em dizer que o código está bem testado . Isso é mais cognoscível, mas ainda é um padrão subjetivo: sempre estará aberto para debater se você o conheceu ou não. Esses debates são úteis e devem ocorrer, mas também expõem a incerteza.

Cobertura de código é uma medida objetiva: uma vez que você vê seu relatório de cobertura, não há ambiguidade sobre se os padrões foram atendidos são úteis. Isso prova correção? Não, mas tem uma relação clara com o quão bem testado é o código, que por sua vez é a nossa melhor maneira de aumentar a confiança em sua correção. Cobertura de código é uma aproximação mensurável de qualidades imensuráveis ​​que nos preocupam.

Alguns casos específicos em que ter um padrão empírico pode agregar valor:

  • Para satisfazer as partes interessadas. Para muitos projetos, existem vários atores que têm interesse em qualidade de software que podem não estar envolvidos no desenvolvimento diário do software (gerentes, líderes técnicos, etc.). Dizendo "vamos escrever todos os os testes de que realmente precisamos "não são convincentes: eles precisam confiar totalmente ou verificar com uma supervisão próxima (supondo que tenham o conhecimento técnico necessário para isso). É melhor fornecer padrões mensuráveis ​​e explicar como eles se aproximam razoavelmente dos objetivos reais.
  • Para normalizar o comportamento da equipe. Partes interessadas à parte, se você estiver trabalhando em uma equipe onde várias pessoas estão escrevendo código e testes, há espaço para ambigüidade para o que se qualifica como "bem testado". Todos os seus colegas têm a mesma ideia de qual nível de teste é bom o suficiente? Provavelmente não. Como você concilia isso? Encontre uma métrica que você possa concordar e aceite-a como uma aproximação razoável. Isso é especialmente (mas não exclusivamente) útil em grandes equipes, onde os leads podem não ter supervisão direta sobre desenvolvedores juniores, por exemplo. As redes de confiança também são importantes, mas sem medidas objetivas, é fácil que o comportamento do grupo se torne inconsistente, mesmo que todos estejam agindo de boa fé.
  • Para se manter honesto. Mesmo que você seja o único desenvolvedor e o único envolvido no seu projeto, você pode ter certas qualidades em mente para o software. Em vez de fazer avaliações subjetivas contínuas sobre o quanto o software é bem testado (o que demanda trabalho), você pode usar a cobertura de código como uma aproximação razoável e permitir que as máquinas o avaliem para você.

Quais métricas usar

A cobertura de código não é uma única métrica; Existem várias maneiras diferentes de medir a cobertura. Qual deles você pode definir um padrão depende do que você está usando esse padrão para satisfazer.

Usarei duas métricas comuns como exemplos de quando você pode usá-las para definir padrões:

  • Cobertura de declaração : Qual porcentagem de declarações foram executadas durante o teste? Útil para obter uma noção da cobertura física do seu código: quanto do código que escrevi já testei?
    • Esse tipo de cobertura suporta um argumento de correção mais fraco, mas também é mais fácil de ser alcançado. Se você está apenas usando a cobertura de código para garantir que as coisas sejam testadas (e não como um indicador de qualidade de teste além disso), a cobertura das declarações provavelmente é suficiente.
  • Cobertura de filiais : quando há lógica de ramificação (por exemplo, um if ), os dois ramos foram avaliados? Isso dá uma noção melhor da cobertura lógica do seu código: Quantos dos caminhos possíveis podem ser usados ​​pelo meu código?
    • Esse tipo de cobertura é um indicador muito melhor de que um programa foi testado em um conjunto abrangente de entradas. Se você estiver usando a cobertura de código como sua melhor aproximação empírica para a confiança na exatidão, deverá definir padrões com base na cobertura de ramificação ou semelhante.

Há muitas outras métricas (a cobertura de linha é semelhante à cobertura de declarações, mas produz resultados numéricos diferentes para instruções de várias linhas, por exemplo, cobertura condicional e cobertura de caminho é semelhante à cobertura de agência, mas reflete uma visão mais detalhada das possíveis permutações de declarações execução do programa que você pode encontrar.)

Qual porcentagem exigir

Finalmente, voltando à pergunta original: Se você definir padrões de cobertura de código, qual deve ser esse número?

Espero que esteja claro neste ponto que estamos falando de uma aproximação para começar, então qualquer número que escolhermos será inerentemente aproximado.

Alguns números que se pode escolher:

  • 100% . Você pode escolher isso porque quer ter certeza de que tudo foi testado. Isso não lhe dá nenhuma ideia da qualidade do teste, mas lhe diz que algum teste de alguma qualidade tocou em cada declaração (ou ramificação, etc.). Novamente, isso volta ao grau de confiança: Se sua cobertura está abaixo de 100% , você sabe que algum subconjunto do seu código não foi testado.
    • Alguns podem argumentar que isso é bobagem, e você só deve testar as partes do seu código que são realmente importantes. Eu diria que você também deve manter apenas as partes do seu código que são realmente importantes. A cobertura de código também pode ser melhorada removendo o código não testado.
  • 99% (ou 95%, outros números nos altos dos noventa). Apropriado nos casos em que você deseja transmitir um nível de confiança semelhante a 100%, mas deixe margem para não se preocupar com o ocasional canto difícil de testar código.
  • 80% . Eu vi esse número em uso algumas vezes e não sei exatamente onde ele se origina. Eu acho que pode ser uma estranha apropriação indevida da regra 80-20; Geralmente, a intenção aqui é mostrar que a maior parte do seu código é testada. (Sim, 51% também seria "a maioria", mas 80% é mais reflexivo do que a maioria das pessoas quer dizer .) Isso é apropriado para casos intermediários em que "bem testado" não é uma alta prioridade (você não Não quero desperdiçar esforço em testes de baixo valor), mas é uma prioridade suficiente que você ainda gostaria de ter algum padrão em vigor.

Eu não vi números abaixo de 80% na prática, e tenho dificuldade em imaginar um caso em que alguém os definiria. O papel desses padrões é aumentar a confiança na correção, e números abaixo de 80% não são particularmente inspiradores de confiança. (Sim, isso é subjetivo, mas, novamente, a ideia é fazer a escolha subjetiva uma vez quando você define o padrão e depois usar uma medida objetiva daqui para frente.)

Outras notas

O acima pressupõe que a correção é o objetivo. Cobertura de código é apenas informação; pode ser relevante para outros objetivos. Por exemplo, se você está preocupado com a capacidade de manutenção, provavelmente se preocupa com o acoplamento flexível, o que pode ser demonstrado pela testabilidade, que por sua vez pode ser medida (em certas formas) pela cobertura de código. Portanto, o seu padrão de cobertura de código fornece uma base empírica para aproximar a qualidade de "manutenibilidade" também.


Confira o Crap4j . É uma abordagem um pouco mais sofisticada do que a cobertura de código direto. Ele combina medições de cobertura de código com medidas de complexidade e, em seguida, mostra o que o código complexo não está sendo testado no momento.


De um modo geral, dos vários documentos de práticas recomendadas de excelência em engenharia que eu li, 80% para novos códigos em testes de unidade é o ponto que produz o melhor retorno. Ir acima desse CC% produz uma quantidade menor de defeitos para a quantidade de esforço exercida. Essa é uma prática recomendada usada por muitas corporações importantes.

Infelizmente, a maioria desses resultados é interna às empresas, portanto não há literaturas públicas que eu possa indicar.


Dependendo da criticidade do código, qualquer valor entre 75% e 85% é uma boa regra prática. O código de envio deve ser testado com mais cuidado do que nos utilitários domésticos, etc.


Esta prosa de Alberto Savoia responde precisamente a essa pergunta (de uma maneira bem divertida!):

http://www.artima.com/forums/flat.jsp?forum=106&thread=204677

Testivus na cobertura de teste

Certa manhã, um programador perguntou ao grande mestre:

“Estou pronto para escrever alguns testes de unidade. Qual cobertura de código devo visar?

O grande mestre respondeu:

"Não se preocupe com cobertura, apenas escreva alguns bons testes."

O programador sorriu, curvou-se e saiu.

...

Mais tarde naquele dia, um segundo programador fez a mesma pergunta.

O grande mestre apontou para uma panela de água fervente e disse:

"Quantos grãos de arroz devo colocar na panela?"

O programador, parecendo intrigado, respondeu:

“Como posso te contar? Depende de quantas pessoas você precisa alimentar, como está com fome, que outros alimentos você está servindo, quanto arroz você tem disponível, e assim por diante. ”

"Exatamente", disse o grande mestre.

O segundo programador sorriu, curvou-se e saiu.

...

No final do dia, um terceiro programador veio e fez a mesma pergunta sobre a cobertura de código.

"Oitenta por cento e não menos!" Respondeu o mestre em uma voz severa, batendo com o punho na mesa.

O terceiro programador sorriu, curvou-se e saiu.

...

Após esta última resposta, um jovem aprendiz se aproximou do grande mestre:

“Grande mestre, hoje ouvi você responder a mesma pergunta sobre a cobertura de código com três respostas diferentes. Por quê?"

O grande mestre levantou-se da cadeira:

"Venha tomar um chá fresco comigo e vamos conversar sobre isso."

Depois de encherem as xícaras de chá verde quente, o grande mestre começou a responder:

“O primeiro programador é novo e está apenas começando a testar. Agora ele tem muito código e nenhum teste. Ele tem um longo caminho a percorrer; concentrar-se na cobertura de código neste momento seria deprimente e inútil. Ele é melhor apenas se acostumar a escrever e executar alguns testes. Ele pode se preocupar com a cobertura depois.

“O segundo programador, por outro lado, é bastante experiente tanto em programação quanto em testes. Quando eu respondi perguntando a ela quantos grãos de arroz eu deveria colocar em uma panela, eu a ajudei a perceber que a quantidade de testes necessários depende de vários fatores, e ela conhece esses fatores melhor do que eu - é o código dela afinal . Não há uma resposta simples e simples, e ela é inteligente o suficiente para lidar com a verdade e trabalhar com isso. ”

“Entendo”, disse o jovem aprendiz, “mas se não houver uma resposta simples, então por que você respondeu ao terceiro programador: 'Oitenta por cento e não menos'?”

O grande mestre riu tão alto e alto que sua barriga, evidência de que ele bebeu mais do que apenas chá verde, pulou para cima e para baixo.

“O terceiro programador quer apenas respostas simples - mesmo quando não há respostas simples ... e depois não as segue de qualquer maneira.”

O jovem aprendiz e o grande mestre grisalho terminaram de beber o chá num silêncio contemplativo.


Eu prefiro fazer o BDD, que usa uma combinação de testes de aceitação automatizada, possivelmente outros testes de integração e testes de unidade. A pergunta para mim é qual deve ser a cobertura de destino da suíte de testes automatizada como um todo.

Além disso, a resposta depende da sua metodologia, linguagem e ferramentas de teste e cobertura. Ao fazer TDD em Ruby ou Python, não é difícil manter 100% de cobertura, e vale a pena fazê-lo. É muito mais fácil gerenciar 100% de cobertura do que 90% de cobertura. Ou seja, é muito mais fácil preencher as lacunas de cobertura à medida que aparecem (e ao fazer as lacunas de cobertura do TDD são raras e geralmente valem a pena) do que gerenciar uma lista de lacunas de cobertura às quais você não teve acesso e perder cobertura regressões devido ao seu histórico constante de código descoberto.

A resposta também depende do histórico do seu projeto. Eu só encontrei o acima para ser prático em projetos gerenciados dessa forma desde o início. Eu melhorei muito a cobertura de grandes projetos legados, e valeu a pena fazê-lo, mas nunca achei prático voltar atrás e preencher todas as lacunas de cobertura, porque o código antigo não testado não é bem entendido o suficiente para fazê-lo corretamente e rapidamente.


Eu teria outro anectode na cobertura de teste que gostaria de compartilhar.

Temos um projeto enorme em que, no Twitter, notei que, com 700 testes unitários, só temos 20% de cobertura de código .

Scott Hanselman respondeu com palavras de sabedoria :

É o direito de 20%? São os 20% que representam o código que seus usuários mais atingem? Você pode adicionar mais 50 testes e adicionar apenas 2%.

Mais uma vez, volta para o meu Testivus sobre Resposta de Cobertura de Código . Quanto arroz você deve colocar no pote? Depende.


Isso deve depender de qual fase do ciclo de vida de desenvolvimento de seu aplicativo você está.

Se você já está no desenvolvimento há algum tempo e já tem um monte de código implementado e só agora percebe que precisa pensar sobre a cobertura de código, então você tem que verificar sua cobertura atual (se existir) e então usar essa linha de base para definir marcos a cada sprint (ou um aumento médio durante um período de sprints), o que significa assumir dívidas de código enquanto continua a fornecer valor ao usuário final (pelo menos na minha experiência o usuário final não se importa um pouco se você aumentou o teste cobertura se eles não virem novos recursos).

Dependendo do seu domínio, não é despropositado fotografar 95%, mas eu tenho que dizer que, em média, você estará olhando para um caso médio de 85% a 90%.


Minha cobertura de código favorita é 100% com um asterisco. O asterisco vem porque eu prefiro usar ferramentas que me permitam marcar certas linhas como linhas que "não contam". Se eu cobri 100% das linhas que "contam", eu terminei.

O processo subjacente é:

  1. Eu escrevo meus testes para exercitar toda a funcionalidade e casos de borda que eu posso pensar (geralmente trabalhando a partir da documentação).
  2. Eu corro as ferramentas de cobertura de código
  3. Eu examino todas as linhas ou caminhos não cobertos e qualquer que eu não considere importante ou inalcançável (devido à programação defensiva) eu marquei como não contando
  4. Eu escrevo novos testes para cobrir as linhas que faltam e aprimoro a documentação se esses casos não forem mencionados.

Dessa forma, se eu e meus colaboradores adicionarmos um novo código ou alterarmos os testes no futuro, há uma linha brilhante para nos informar se perdemos algo importante - a cobertura caiu abaixo de 100%. No entanto, também oferece flexibilidade para lidar com diferentes prioridades de teste.


Muitas lojas não avaliam testes, então se você está acima de zero, pelo menos, há alguma valorização - então, sem dúvida, não-zero não é ruim, pois muitos ainda são zero.

No mundo do .Net, as pessoas costumam citar 80% como razoáveis. Mas eles dizem isso no nível da solução. Eu prefiro medir a nível de projeto: 30% pode ser bom para o projeto de interface do usuário se você tiver selênio, etc ou testes manuais, 20% para o projeto de camada de dados pode ser bom, mas 95% + pode ser bastante viável para o negócio camada de regras, se não for totalmente necessário. Portanto, a cobertura total pode ser, digamos, 60%, mas a lógica de negócios crítica pode ser muito maior.

Eu também ouvi isso: aspirar a 100% e você chegará a 80%; mas aspire a 80% e você chegará a 40%.

Resumindo: aplique a regra 80:20 e deixe a contagem de erros do aplicativo guiá-lo.


Na minha opinião, a resposta é "depende de quanto tempo você tem". Eu tento atingir 100%, mas eu não faço barulho se eu não conseguir com o tempo que eu tenho.

Quando escrevo testes de unidade, uso um chapéu diferente do chapéu que uso quando desenvolvo código de produção. Eu penso sobre o que o código testado afirma fazer e quais são as situações que podem ser quebradas.

Eu costumo seguir os seguintes critérios ou regras:

  1. Que o Teste de Unidade deve ser uma forma de documentação sobre qual é o comportamento esperado dos meus códigos, ie. a saída esperada dada uma determinada entrada e as exceções que ela pode lançar que os clientes podem querer capturar (O que os usuários do meu código devem saber?)

  2. Que o Teste de Unidade me ajude a descobrir quais são as condições que eu ainda não pensei. (Como tornar meu código estável e robusto?)

Se estas duas regras não produzem 100% de cobertura, então que seja. Mas uma vez, tenho tempo, analiso os blocos e linhas descobertos e determino se ainda há casos de teste sem testes de unidade ou se o código precisa ser refatorado para eliminar os códigos desnecessários.


Quando eu acho que o meu código não é testado o suficiente, e não tenho certeza do que testar em seguida, uso a cobertura para me ajudar a decidir o que testar em seguida.

Se eu aumentar a cobertura em um teste de unidade - eu sei que esse teste de unidade vale alguma coisa.

Isso vale para código que não é coberto, 50% coberto ou 97% coberto.


Resposta curta: 60-80%

Resposta longa: acho que depende totalmente da natureza do seu projeto. Eu normalmente inicio um projeto por unidade testando cada peça prática. Pela primeira "versão" do projeto, você deve ter uma boa porcentagem de base com base no tipo de programação que está fazendo. Nesse ponto, você pode começar a "impingir" uma cobertura de código mínima.


Se você tem feito testes unitários por um período decente de tempo, não vejo razão para não se aproximar dos 95% +. No entanto, no mínimo, sempre trabalhei com 80%, mesmo quando novo no teste.

Este número deve incluir apenas o código escrito no projeto (exclui frameworks, plugins, etc.) e talvez até mesmo excluir certas classes compostas inteiramente de código escrito de chamadas para código externo. Esse tipo de ligação deve ser ridicularizado / stubbed.


Visualizando a cobertura de outra perspectiva: Código bem escrito com um fluxo claro de controle é o mais fácil de cobrir, o mais fácil de ler e, geralmente, o código com menos bugs. Ao escrever código com clareza e capacidade de cobertura em mente, e escrevendo os testes de unidade em paralelo com o código, você obtém os melhores resultados IMHO.


Fomos alvo de> 80% até poucos dias atrás, mas depois usamos muito código gerado. Não nos importamos com% age, mas sim, fazemos o revisor atender à cobertura necessária.


A partir do post de Testivus, acho que o contexto de resposta deve ser o segundo programador. Tendo dito isso de um ponto de vista prático, precisamos de parâmetros / metas pelos quais lutar. Eu considero que isso pode ser "testado" em um processo ágil analisando o código que temos a arquitetura, a funcionalidade (histórias de usuário) e, em seguida, criar um número. Com base na minha experiência na área de Telecom, eu diria que 60% é um bom valor para verificar.





code-metrics