Introdução: Por que testes "verdes" ainda não são uma vitória?
\n\nImagine: você executa mil unit-testes, todos passam com a marca verde, o pipeline de CI está feliz, o gerente está satisfeito. Mas passa uma semana e um bug crítico cai em produção. Situação familiar? Na maioria das vezes, o problema é que os testes existem, mas eles não verificam o código realmente executado. Eles podem testar apenas 10% dos fontes, enquanto os outros 90% são uma "zona cinzenta" onde os erros se escondem.
\n\nÉ aqui que entra em cena a cobertura de código com testes em C++ (code coverage). Não é apenas uma métrica da moda para relatar ao cliente. É o seu raio-X que mostra: quais linhas de código são realmente executadas durante os testes e quais nunca foram executadas. Hoje, vamos analisar como configurar corretamente as ferramentas de cobertura em C++, quais métricas são realmente importantes e como não se afogar em falsos positivos.
\n\nO que é cobertura de código e por que ela é necessária para o desenvolvedor C++?
\n\nCobertura de código (code coverage) é uma métrica que mostra qual porcentagem do código-fonte do seu programa foi executada durante a execução dos testes. Em C++, isso é especialmente crítico porque a linguagem permite escrever código de baixo nível, otimizações e magia de templates que podem "disparar" no momento mais inesperado.
\n\nPrincipais tipos de métricas de cobertura
\nNem todas as métricas são igualmente úteis. Aqui está o que realmente importa:
\n- \n
- Line Coverage (cobertura de linhas) — a métrica mais básica. Quantas linhas do fonte foram afetadas. Fácil de medir, mas fácil de enganar. \n
- Branch Coverage (cobertura de ramificações) — verifica se ambos os ramos de cada
if/elseouswitchforam percorridos. Muito mais honesto que a cobertura de linhas. \n - Function Coverage (cobertura de funções) — se a função foi chamada pelo menos uma vez. Útil para encontrar código "morto". \n
- Condition Coverage (cobertura de condições) — verifica todas as subexpressões em operadores lógicos complexos (
&&,||). O mais rigoroso, mas também o mais intensivo em recursos. \n
Para um projeto C++ comum, é considerado boa prática ter uma meta de 70-80% de cobertura de linhas e pelo menos 60% de cobertura de ramificações. 100% de cobertura é uma utopia, mas buscar 90% em módulos críticos (gerenciamento de memória, protocolos de rede) é uma tarefa perfeitamente realista.
\n\nFerramentas para análise de cobertura de código C++
\n\nO ecossistema C++ oferece várias ferramentas poderosas. Vamos analisar as 3 principais que são realmente usadas em produção.
\n\n1. Gcov — o clássico do GCC
\ngcov é uma ferramenta embutida no compilador GCC. Ela funciona no nível do código de máquina, portanto fornece resultados muito precisos. Principais vantagens: gratuito, aberto, funciona com CMake e Makefile.
Como executar:
\n// Compilamos com flags de cobertura\ng++ -fprofile-arcs -ftest-coverage -O0 main.cpp -o test_app\n\n// Executamos os testes\n./test_app\n\n// Geramos o relatório\ngcov main.cpp\nDepois disso, você obterá arquivos *.gcov, onde será mostrado quantas vezes cada linha foi executada. Desvantagem: o formato de saída é textual, não muito visual.
2. LCOV — interface gráfica para Gcov
\nlcov é uma extensão do gcov que gera belos relatórios HTML. Você poderá ver linhas verdes (cobertas) e vermelhas (não cobertas) diretamente no navegador.
# Coletamos os dados de cobertura\nlcov --capture --directory . --output-file coverage.info\n\n# Geramos o HTML\ngenhtml coverage.info --output-directory coverage_report\nEste é o padrão da indústria para CI/CD. Jenkins, GitLab CI, GitHub Actions — em todos eles é possível configurar a geração automática do LCOV.
\n\n3. Clang Sanitizer Coverage (baseado em fonte)
\nSe você usa Clang, tem acesso ao -fsanitize-coverage. E