Este é um projeto educacional que demonstra a diferença entre cobertura de testes e qualidade de testes.
O projeto implementa uma calculadora de preços com desconto simples, mas usa-a para ilustrar um conceito crucial:
Cobertura de testes 100% ≠ Testes bons/adequados
Mesmo quando todas as linhas de código são executadas pelos testes, eles podem não estar detectando bugs reais. Este projeto mostra essa lacuna usando:
- Coverlet: Mede a cobertura de código que os casos de teste cobrem
- Stryker: Aplica mutações propositais ao código para verificar se os testes conseguem detectá-las
T1/
├── lib/
│ ├── PriceCalculator.cs # Código da biblioteca (a lógica a testar)
│ └── PriceCalculator.csproj # Projeto de produção (.NET)
├── tests/
│ ├── PriceCalculatorTest.cs # Testes unitários (xUnit)
│ └── PriceCalculatorTest.csproj # Projeto de testes (.NET)
├── PriceCalculator.sln # Solução que agrupa os projetos
├── coveragereport/ # Relatório de cobertura (Coverlet)
├── StrykerOutput/ # Relatório de mutação (Stryker)
└── README.md # Este arquivo
dotnet tool restoreIsto instala Stryker e ReportGenerator como ferramentas locais no projeto.
dotnet restoreExecute os testes xUnit para validar que a lógica está funcionando:
dotnet test tests/PriceCalculatorTest.csprojResultado esperado: 3 testes passando
- ✅ Cálculo correto de desconto (100 - 10% = 90)
- ✅ Validação de desconto inválido (< 0 ou > 100)
- ✅ Validação de preço inválido (≤ 0)
Coverlet é um instrumento de cobertura de código open-source que mede quantas linhas de código são executadas pelos testes. Diferentemente do Stryker que valida a qualidade dos testes, Coverlet mede apenas a quantidade de código testado.
- ✅ Rastreia quais linhas foram executadas
- ✅ Rastreia quais branches (caminhos) foram executados
- ✅ Gera relatórios em múltiplos formatos (Cobertura XML, JSON, etc.)
- ❌ NÃO valida se os testes realmente detectam bugs
dotnet test tests/PriceCalculatorTest.csproj --settings .runsettings --collect:"XPlat Code Coverage"Isto gera um arquivo XML em tests/TestResults/*/coverage.cobertura.xml
reportgenerator -reports:"**/coverage.cobertura.xml" -targetdir:"coveragereport" -reporttypes:HtmlStart-Process "coveragereport/index.html"Resultado esperado: ~96% de cobertura de linhas
Stryker é muito mais rigoroso que cobertura. Ele modifica seu código propositalmente (cria mutantes) e verifica se os testes detectam essas modificações.
- Stryker aplica mutações ao código (ex:
<=vira<,*vira/) - Roda os testes para cada mutação
- Se os testes ainda passam, significa que o teste não detectou o bug
- Calcula o kill score: percentual de mutações detectadas
dotnet strykerResultado esperado:
- 11 mutantes mortos (testes detectaram)
- 5 mutantes vivos (testes não detectaram)
- Kill Score: 68.75% ← Mesmo com cobertura alta!
Após a execução, abra o relatório gerado:
Start-Process "StrykerOutput/*/reports/mutation-report.html"Observe o contraste:
| Métrica | Resultado |
|---|---|
| Cobertura de Linhas (Coverlet) | ~96% ✅ |
| Kill Score (Stryker) | 68.75% ❌ |
Mesmo com 96% de cobertura de linhas e 100% de cobertura de branchs, apenas 68.75% dos mutantes foram detectados. Isto demonstra que:
- ✅ Todas as linhas foram executadas
- ❌ Mas os testes não validam todos os comportamentos
- ❌ Se esses "mutantes" fossem bugs reais, os testes desse projeto não os pegariam
Para entender melhor os conceitos por trás deste projeto:
- Coverlet - Code Coverage: GitHub Coverlet — Framework de cobertura de código para .NET
- Teste de Mutação no .NET: Microsoft Learn - Mutation Testing
- Stryker.NET - Getting Started: Stryker Mutator Docs
- Fundamentos de Teste de Mutação: IEEE - Mutation Testing (Jia & Harman, 2011)
- Se você clonar este repositório em outra máquina, execute
dotnet tool restorepara restaurar ferramentas locais - Os relatórios gerados (coveragereport/ e StrykerOutput/) são ignorados pelo git
- Este é um projeto de propósito educacional