Cobertura diz que a linha rodou
A suíte de testes deste repositório reporta 82,99% de cobertura de linhas em 1.206 exemplos. É um número respeitável, e este curso é sobre o que nem um número perfeito contaria.
$ bundle exec rspec
1206 examples, 1 failure
Line Coverage: 82.99% (4190 / 5049)
Aqui está o que esse número significa e o que não significa.
O que cobertura de linhas mede
O SimpleCov instrumenta o interpretador e registra quais linhas executaram durante a execução. 4190 linhas de 5049 rodaram pelo menos uma vez. Essa é a afirmação inteira. (A única falha é um spec de fuso horário que depende do tzdata da máquina local.)
Ela diz que uma linha rodou. Não diz nada sobre se algo checou o resultado. Um spec que chama um método e não afirma nada produz a mesma cobertura que um spec que afirma tudo sobre ele. E a cobertura não consegue distingui-los porque a diferença é invisível ao instrumento.
flowchart TB
A["um spec roda uma linha"] --> B["cobertura de linha: coberta"]
A --> C{"algo afirmou sobre o resultado?"}
C -->|"sim"| D["a linha está testada"]
C -->|"não"| E["a linha está executada"]
B --> F["a cobertura não distingue D de E"]
O experimento
O teste de mutação responde a pergunta que a cobertura não responde. E responde do único jeito possível: quebre o código de propósito, e veja se a suíte percebe.
Mude uma coisa na aplicação. Rode a suíte. Se um teste falhar, a mutação foi morta: algo checava aquele comportamento. Se a suíte continuar passando, a mutação sobreviveu, e você achou uma linha que roda sem ser testada.
Aqui está uma, rodada contra este repositório. O app/services/auth/password_policy.rb declara:
MIN_LENGTH = 8
Mude para 7 e rode todos os 1.206 exemplos:
SURVIVED | MIN_LENGTH = 8 -> MIN_LENGTH = 7 | 1206 examples, 1 failure (the tzdata spec)
A suíte continua verde com o comprimento mínimo de senha enfraquecido.
Aquela linha está coberta. Ela é referenciada pela validação de comprimento do Identity::User, por três views, um controller Stimulus, e por um arquivo de spec chamado spec/services/auth/password_policy_spec.rb. Cada um deles a executa. Nenhum deles a checa.
Por que essa é a medição honesta
Uma suíte de testes existe para falhar quando o código está errado. Esse é o único trabalho dela. Então o jeito direto de avaliar uma suíte é errar o código e ver se ela falha, que é o que o teste de mutação faz. E por que o resultado se chama cobertura de mutação e não uma estimativa.
| Métrica | Pergunta que responde | O que um número alto prova |
|---|---|---|
| Cobertura de linha | Esta linha executou? | O código é alcançável |
| Cobertura de ramo | Os dois lados deste if executaram? |
Os dois caminhos são alcançáveis |
| Cobertura de mutação | A suíte falha quando esta linha está errada? | O comportamento está verificado |
Cobertura de linha não é inútil: uma linha em 0% está definitivamente sem teste, e achar essas é barato. Ela é um limite inferior da ignorância, não uma medida de qualidade. A cobertura de mutação é a medida de qualidade, e custa muito mais para calcular, que é a troca sobre a qual é o resto deste curso.
O que esperar
A próxima aula é o catálogo de mutações. A aula 3 é o experimento completo neste repositório: onze mutações, seis mortas, cinco sobreviventes, com os resultados. A aula 4 é a parte que todo relato honesto inclui: mutações que sobrevivem e deveriam, e por que a triagem é o custo real.
Pontos-chave
- Esta suíte tem 82,99% de cobertura de linhas em 1.206 exemplos.
- A cobertura de linha registra que uma linha executou; não enxerga se algo afirmou sobre o resultado.
- O teste de mutação quebra o código deliberadamente e pergunta se a suíte falha: morta, ou sobreviveu.
- Medido aqui:
MIN_LENGTH = 8trocado por7deixa todos os 1.206 exemplos verdes. - Cobertura de linha é um limite inferior da ignorância; cobertura de mutação é a medida de comportamento verificado.
Continue com a aula 2
Os operadores de mutação
As famílias de mutação, de fronteiras a remoções de chamada, e os termos morta, viva, timeout, noop e equivalente.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.