Por que testes "verdes" ainda não são uma vitória?
\n\nImagine: você escreveu uma centena de testes unitários, todos passam com um visto verde, o pipeline de CI está feliz, o gerente está satisfeito. Mas um mês depois, uma funcionalidade crítica cai em produção. História familiar? Na maioria das vezes, o problema é que testamos os cenários errados ou pulamos ramos inteiros de código.
\n\nA cobertura de código com testes (code coverage) não é apenas uma métrica da moda para relatórios. É a sua lanterna no quarto escuro da incerteza. Quando comecei a trabalhar com C#, pensei que 80% de cobertura era o ideal. Mas depois percebi: você pode ter 100% de cobertura de linhas e ainda assim perder um bug na lógica de ramificação. Por isso, hoje vamos entender como medir corretamente a cobertura em C#, quais ferramentas realmente ajudam e quais métricas vale a pena acompanhar.
\n\nO que é cobertura de código e por que é importante para o desenvolvedor C#?
\n\nSimplificando, a cobertura de código mostra qual porcentagem do código-fonte da sua aplicação foi executada durante a execução dos testes. Se você escreveu um teste que chama o método CalculateDiscount(), mas não verifica o ramo if (isPremiumUser), esse ramo permanece "descoberto".
Para o desenvolvedor C#, a cobertura é um indicador de duas coisas:
\n- \n
- Confiança na refatoração — é possível alterar o código sem medo de quebrar algo? \n
- Completude dos testes — não nos esquecemos dos casos limite? \n
Mas há uma nuance importante: a cobertura de código com testes em C# não garante a ausência de bugs. Ela apenas indica que certas linhas foram executadas. É por isso que não olhamos apenas para a porcentagem, mas para métricas específicas.
\n\nPrincipais métricas de cobertura de código no .NET
\n\nAo executar a análise de cobertura em C#, você encontrará vários tipos de métricas. Vamos analisar cada uma com um exemplo de código real.
\n\nLine Coverage (cobertura de linhas)
\nA métrica mais simples. Conta quantas linhas de código foram tocadas pelos testes. Exemplo:
\n\npublic int Add(int a, int b)\n{\n if (a < 0) // linha 1\n return 0; // linha 2\n return a + b; // linha 3\n}\n\nSe o seu teste chama Add(5, 3), as linhas 1 e 3 serão executadas. A linha 2 permanecerá descoberta. O Line coverage mostrará 66% (2 de 3 linhas).
Branch Coverage (cobertura de ramificações)
\nUma métrica mais honesta. Ela considera todos os caminhos possíveis de execução. No nosso exemplo, existem dois caminhos: quando a < 0 e quando não. Se você testou apenas o caso com número positivo, o Branch coverage será de 50%.
É o Branch coverage que frequentemente revela "buracos" nos testes. Recomendo buscar 80%+ especificamente nesta métrica.
\n\nCyclomatic Complexity e sua relação com a cobertura
\nEmbora não seja uma métrica direta de cobertura, a complexidade ciclomática mostra quantos testes são necessários para uma cobertura completa. Quanto maior a complexidade do método, mais testes são necessários. Se você vê um método com complexidade ciclomática 15 e cobertura de 90%, provavelmente não está testando todos os cenários.
\n\nFerramentas para medir cobertura de código em C#
\n\nNo ecossistema .NET, existem várias ferramentas poderosas. Vou falar sobre as três mais populares com as quais já trabalhei.
\n\nCoverlet — gratuito e integrado ao .NET
\nSe você usa .NET 6+, o Coverlet já está disponível via NuGet. É minha ferramenta favorita para CI/CD, pois não requer instalação de programas adicionais.
\n\nInstalação:
\ndotnet add package coverlet.msbuild\ndotnet add package coverlet.collector\n\nExecução com relatório:
\ndotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover\n\nVocê obterá o arquivo coverage.opencover.xml, que pode ser visualizado com o ReportGenerator:
dotnet tool install -g dotnet-reportgenerator-globaltool\nreportgenerat