Code Coverage (cobertura de código) é uma métrica que mostra qual porcentagem do código-fonte do aplicativo é executada durante os testes. Ela ajuda a determinar a qualidade dos testes, identificar áreas não verificadas e priorizar a escrita de novos testes. De acordo com a Atlassian, 2025, o nível ideal de cobertura é de 70–80% — acima desse limite, os custos dos testes começam a superar os benefícios.
Principais conclusões
Code Coverage (cobertura de código) é uma métrica quantitativa que determina qual parte do código-fonte do aplicativo foi executada durante os testes. É expressa em porcentagem e calculada como a razão entre linhas/ramos executados e o total. Alta cobertura não garante ausência de bugs, mas reduz o risco de erros não detectados.
A cobertura de código ajuda a equipe a: encontrar áreas não testadas do código, tomar decisões sobre prioridades de escrita de testes e acompanhar a dinâmica da qualidade dos testes em CI/CD. No desenvolvimento mobile, a cobertura é especialmente importante para a lógica de negócios, modelos de dados e repositórios — camadas onde a probabilidade de erros é maior.
Um mito comum: “100% de cobertura = qualidade perfeita”. Na prática, 100% de cobertura é extremamente raro e muitas vezes alcançado à custa de testes superficiais. Cobertura eficaz não é uma corrida por porcentagem, mas uma cobertura estratégica de caminhos críticos e condições de fronteira. A cobertura não diz nada sobre a qualidade dos próprios testes: um teste pode passar mas não verificar a correção do resultado.
Existem várias métricas de Code Coverage, cada uma medindo diferentes aspectos dos testes. Line coverage (cobertura de linha) é a métrica mais simples, mostrando a porcentagem de linhas de código executadas. Branch coverage (cobertura de ramo) mede quais ramificações if-else e switch foram testadas.
Line coverage conta cada linha de código-fonte como executada ou não. Se uma linha contém um operador condicional ou loop, a linha é considerada executada se o controle a alcançou, mesmo que nem todos os ramos tenham sido processados. Esta é a métrica menos rigorosa, mas a mais compreensível para avaliação visual.
Branch coverage avalia se todos os possíveis ramos no código foram testados. Para cada if-else, ambos os ramos são considerados: true e false. Para switch, cada case é considerado. Branch coverage é considerada uma métrica mais rigorosa que line coverage e mais frequentemente revela cenários não testados.
| Métrica | O que mede | Dificuldade de alcançar |
|---|---|---|
| Line | Porcentagem de linhas de código executadas | Baixa |
| Branch | Porcentagem de ramos executados (if/else, switch) | Média |
| Function | Porcentagem de funções e métodos chamados | Baixa |
| Condition | Porcentagem de subexpressões lógicas (&&, ||) | Alta |
Path coverage é a métrica mais rigorosa, exigindo verificação de todas as possíveis combinações de ramos em uma função. Na prática, path coverage raramente é usado devido ao crescimento exponencial do número de combinações: uma função com 10 ramos tem 1024 caminhos possíveis.
No desenvolvimento mobile, várias ferramentas são usadas para medir Code Coverage dependendo da plataforma. Para Android, o padrão é JaCoCo (Java Code Coverage), que se integra com Gradle e suporta tanto testes unitários quanto testes de instrumentação. Para iOS, é usado o XCCov, integrado ao Xcode.
JaCoCo gera relatórios nos formatos HTML, XML e CSV. O relatório HTML destaca visualmente as linhas: verde — executadas, vermelho — omitidas, amarelo — parcialmente executadas. O relatório XML é compatível com SonarQube e outros sistemas de análise de código. JaCoCo suporta filtragem de classes: código gerado, databinding e BuildConfig podem ser excluídos.
// build.gradle — configuração do JaCoCo
android {
buildTypes {
debug {
testCoverageEnabled = true
}
}
}
// Geração de relatório JaCoCo
task jacocoTestReport(type: JacocoReport) {
dependsOn 'testDebugUnitTest'
reports {
xml.enabled = true
html.enabled = true
}
}
XCCov é uma ferramenta integrada do Xcode para medir cobertura de código. É habilitada através de Gather coverage data no esquema de teste. XCCov suporta cobertura para Swift e Objective-C, gera relatórios no formato .xccovreport e se integra com CI via xcodebuild -enableCodeCoverage YES. Os dados são exibidos no console e podem ser exportados em JSON.
Para monitoramento centralizado de cobertura, são usadas plataformas como SonarQube (análise de qualidade de código + cobertura), Codecov e Coveralls. Esses serviços agregam dados do JaCoCo e XCCov, mostram tendências, Quality Gate e integração com GitHub/GitLab através de comentários em PR.
Melhorar o Code Coverage requer uma abordagem sistemática: não “aumentar porcentagens”, mas cobrir riscos. O primeiro passo é analisar o relatório JaCoCo ou XCCov — identificar classes vermelhas (não cobertas). Prioridade: lógica de negócios → repositórios → ViewModel → componentes de UI.
Test-Driven Development (TDD) garante automaticamente alta cobertura, pois os testes são escritos antes da implementação. O processo: vermelho (escrever um teste que falha) → verde (escrever código mínimo) → refatoração. TDD disciplina o desenvolvedor, forçando-o a cobrir casos limite e situações excepcionais que frequentemente ficam sem teste.
Um teste parametrizado substitui dezenas de testes comuns. JUnit e XCTest suportam parametrização: @ParameterizedTest no JUnit 5, XCTestCase com testPerformanceExample no XCTest. A parametrização permite verificar múltiplos dados de entrada sem duplicação de código, expandindo significativamente a cobertura de ramos e condições.
// Teste parametrizado em Kotlin com JUnit 5
@ParameterizedTest
@ValueSource(strings = ["user@test.com", "admin@test.com", "test@example.com"])
fun `validate email returns true for valid addresses`(email: String) {
val result = EmailValidator.isValid(email)
Assertions.assertTrue(result)
}
O erro mais comum é perseguir a porcentagem sem analisar a qualidade dos testes. A equipe começa a escrever testes por escrever: verifica getters e setters, duplica cobertura em diferentes níveis, testa métodos triviais. Isso dá uma alta porcentagem mas não melhora a qualidade real.
Um Code Coverage alto pode criar uma falsa sensação de que o aplicativo está bem testado. Um teste pode executar uma linha de código mas não verificar a correção do resultado. Por exemplo: um teste chama um método de cálculo de desconto mas não verifica o valor — a linha é executada, a cobertura cresce, mas o bug não é encontrado.
Um erro típico é testar apenas o “caminho feliz” (happy path) e ignorar casos limite: listas vazias, valores null, números máximos, formatos incorretos. É precisamente nos limites e exceções que a maioria dos bugs ocorre. Branch coverage ajuda a identificar ramos perdidos, mas não garante a verificação de valores limite.
Mutation Testing é um método para avaliar a qualidade dos testes onde mutações (erros artificiais) são introduzidas no código-fonte e verifica-se se os testes falham. Pitest é uma ferramenta popular de mutation testing para Java e Kotlin. Se os testes não falham em uma mutação, significa que eles não verificam essa condição.
Pitest cria mutantes — cópias modificadas do código-fonte onde, por exemplo, > é substituído por >=, true por false, ou uma chamada de método é removida. Então, para cada mutante, os testes são executados. Se os testes passam — o mutante sobreviveu, significando que os testes não cobrem esse cenário. Se os testes falham — o mutante foi morto, o teste é válido.
// build.gradle — configuração do Pitest
plugins {
id 'info.solidsoft.pitest' version '1.15.0'
}
pitest {
targetClasses = ['com.example.app.*']
targetTests = ['com.example.app.*Test']
threads = 4
outputFormats = ['HTML', 'XML']
mutationThreshold = 80
coverageThreshold = 85
}
Pitest suporta muitos tipos de mutação: alteração de operadores condicionais (== → !=, < → <=), remoção de chamadas de método, substituição de valores de retorno (true → false), alteração de operações aritméticas (+ → -), mutação de incrementos (i++ → i--). Quanto mais tipos de mutação são mortos pelos testes, mais confiável é o conjunto de testes.
O mutation score alvo é 80% ou mais. Isso significa que 80% dos erros artificiais são detectados pelos testes. Uma cobertura de código (Code Coverage) de 90% não garante que os testes encontrem bugs — o mutation testing fornece uma avaliação mais objetiva. Pitest pode ser integrado ao CI como Quality Gate, bloqueando o build se o mutation score cair abaixo do limite.
Para controle automático do Code Coverage em CI/CD, são usados Quality Gates — valores limite que, quando violados, marcam o build como instável ou o rejeitam. SonarQube permite configurar um Quality Gate baseado em uma combinação de métricas: cobertura (≥80%), número de bugs, vulnerabilidades e código duplicado.
No GitHub Actions, o Code Coverage é integrado através de etapas de ação: executar testes com cobertura → enviar relatório para Codecov → verificar limite. Codecov automaticamente comenta nos PRs com o diff de cobertura, mostrando quais linhas mudaram e como isso afetou a porcentagem geral. Se a cobertura caiu, o PR é bloqueado até que testes adicionais sejam escritos.
# GitHub Actions — envio de cobertura para Codecov
- name: Run Tests with Coverage
run: ./gradlew testDebugUnitTest jacocoTestReport
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
files: ./app/build/reports/jacoco/jacocoTestReport.xml
flags: unittests
fail_ci_if_error: true
- name: Check Coverage Threshold
run: |
coverage=$(grep -oP 'branchCoverage="\K[0-9.]+' report.xml)
if (( $(echo "$coverage < 80" | bc -l) )); then
echo "Coverage $coverage% is below 80% threshold"
exit 1
fi
Relatórios HTML do JaCoCo e XCCov contêm destaque visual de cobertura: verde — linhas executadas, vermelho — não executadas. SonarQube adicionalmente mostra cobertura no nível de arquivo, classe, método e linha, bem como o histórico de alteração de cobertura por sprints. Isso ajuda a tomar decisões sobre refatoração e adição de testes.
Perguntas frequentes
Para projetos mobile, cobertura de 70–80% para lógica de negócios e 50–60% para componentes de UI é considerada boa. Acima de 80%, os custos de teste começam a superar os benefícios. É importante lembrar que a porcentagem não é um objetivo, mas um indicador, e diferentes módulos podem ter diferentes níveis alvo.
Line Coverage mostra quantas linhas de código foram executadas. Branch Coverage mostra quantas ramificações (if-else, switch) foram testadas. Uma linha com if pode ser executada, mas apenas o ramo true pode ter sido testado, e não o false. Branch Coverage é mais rigorosa e revela mais cenários perdidos.
Em CI/CD, a cobertura é integrada através de um Quality Gate: o build é bloqueado se a cobertura estiver abaixo do limite. Para Android, usa-se JaCoCo + SonarQube; para iOS — xcodebuild -enableCodeCoverage com análise de .xccovreport. GitHub Actions tem ações prontas para Codecov.
Sim, JaCoCo suporta Jetpack Compose através do mecanismo padrão de cobertura JVM. No entanto, o código Compose contém muitas expressões lambda geradas que o JaCoCo pode não cobrir completamente. Recomenda-se excluir o código Compose gerado do relatório através de filtros.
Cobertura falsa ocorre quando um teste executa código mas não verifica o resultado. Solução: escrever asserções para cada cenário importante, usar mutation testing (Pitest) para verificar a qualidade dos testes, analisar não apenas a porcentagem mas também quais ramos estão cobertos.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também