Code Coverage nello sviluppo mobile: cos'è, metriche e come misurarlo

Autore: IT Sectr Pubblicato: 2026-04-09 Tempo di lettura: 9 min

Il Code Coverage (copertura del codice) è una metrica che mostra quale percentuale del codice sorgente di un'applicazione viene eseguita durante i test. Aiuta a determinare la qualità dei test, identificare aree non verificate e prioritizzare la scrittura di nuovi test. Secondo Atlassian, 2025, il livello ottimale di copertura è del 70–80% — oltre questa soglia, i costi dei test iniziano a superare i benefici.

Punti chiave

  • Code Coverage — metrica che misura la percentuale di codice eseguito dai test
  • Metriche di copertura includono linea (line), ramo (branch), funzioni, condizioni e percorsi
  • Strumenti: JaCoCo per Android, XCCov per iOS, SonarQube per l'analisi del codice
  • Copertura target 70–80% — equilibrio tra qualità e costo dei test
  • Integrazione CI/CD consente di bloccare i build quando la copertura scende sotto la soglia

Cos'è il Code Coverage

Code Coverage (copertura del codice) è una metrica quantitativa che determina quale parte del codice sorgente dell'applicazione è stata eseguita durante i test. Viene espressa in percentuale e calcolata come rapporto tra linee/rami eseguiti e il totale. Un'elevata copertura non garantisce l'assenza di bug, ma riduce il rischio di errori non rilevati.

Perché misurare la copertura

La copertura del codice aiuta il team a: trovare aree non testate del codice, prendere decisioni sulle priorità di scrittura dei test e monitorare la dinamica della qualità dei test in CI/CD. Nello sviluppo mobile, la copertura è particolarmente importante per la logica di business, i modelli di dati e i repository — i livelli in cui la probabilità di errori è più alta.

Miti sul Code Coverage

Un mito comune: “100% di copertura = qualità perfetta”. In pratica, la copertura al 100% è estremamente rara e spesso ottenuta a costo di test superficiali. La copertura efficace non è una corsa alla percentuale, ma una copertura strategica dei percorsi critici e dei casi limite. La copertura non dice nulla sulla qualità dei test stessi: un test può superare ma non verificare la correttezza del risultato.

Metriche di copertura del codice

Esistono diverse metriche di Code Coverage, ognuna misura aspetti diversi dei test. Line coverage (copertura di linea) è la metrica più semplice, che mostra la percentuale di linee di codice eseguite. Branch coverage (copertura di ramo) misura quali ramificazioni if-else e switch sono state testate.

Copertura di linea (Line Coverage)

Line coverage conta ogni linea di codice sorgente come eseguita o meno. Se una linea contiene un operatore condizionale o un ciclo, la linea è considerata eseguita se il controllo l'ha raggiunta, anche se non tutti i rami sono stati elaborati. Questa è la metrica meno rigorosa, ma la più comprensibile per la valutazione visiva.

Copertura di ramo (Branch Coverage)

Branch coverage valuta se tutti i possibili rami nel codice sono stati testati. Per ogni if-else, entrambi i rami sono considerati: true e false. Per switch, ogni case è considerato. Branch coverage è considerata una metrica più rigorosa di line coverage e rivela più spesso scenari non testati.

MetricaCosa misuraDifficoltà di raggiungimento
LinePercentuale di linee di codice eseguiteBassa
BranchPercentuale di rami eseguiti (if/else, switch)Media
FunctionPercentuale di funzioni e metodi chiamatiBassa
ConditionPercentuale di sottoespressioni logiche (&&, ||)Alta

Copertura di percorso (Path Coverage)

Path coverage è la metrica più rigorosa, che richiede la verifica di tutte le possibili combinazioni di rami in una funzione. In pratica, path coverage è raramente utilizzato a causa della crescita esponenziale del numero di combinazioni: una funzione con 10 rami ha 1024 percorsi possibili.

Strumenti per misurare la copertura

Nello sviluppo mobile, vengono utilizzati vari strumenti per misurare il Code Coverage a seconda della piattaforma. Per Android, lo standard è JaCoCo (Java Code Coverage), che si integra con Gradle e supporta sia test unitari che test di strumentazione. Per iOS viene utilizzato XCCov, integrato in Xcode.

JaCoCo per Android

JaCoCo genera report nei formati HTML, XML e CSV. Il report HTML evidenzia visivamente le linee: verde — eseguite, rosso — saltate, giallo — parzialmente eseguite. Il report XML è compatibile con SonarQube e altri sistemi di analisi del codice. JaCoCo supporta il filtraggio delle classi: è possibile escludere codice generato, databinding e BuildConfig.

groovy
// build.gradle — configurazione JaCoCo
android {
    buildTypes {
        debug {
            testCoverageEnabled = true
        }
    }
}

// Generazione report JaCoCo
task jacocoTestReport(type: JacocoReport) {
    dependsOn 'testDebugUnitTest'
    reports {
        xml.enabled = true
        html.enabled = true
    }
}

XCCov per iOS

XCCov è uno strumento integrato in Xcode per misurare la copertura del codice. Si attiva tramite Gather coverage data nello schema di test. XCCov supporta la copertura per Swift e Objective-C, genera report in formato .xccovreport e si integra con CI tramite xcodebuild -enableCodeCoverage YES. I dati vengono visualizzati nella console e possono essere esportati in JSON.

SonarQube e Codecov

Per il monitoraggio centralizzato della copertura, vengono utilizzate piattaforme come SonarQube (analisi della qualità del codice + copertura), Codecov e Coveralls. Questi servizi aggregano dati da JaCoCo e XCCov, mostrano tendenze, Quality Gate e integrazione con GitHub/GitLab tramite commenti PR.

Come migliorare la copertura del codice

Migliorare il Code Coverage richiede un approccio sistematico: non “aumentare le percentuali”, ma coprire i rischi. Il primo passo è analizzare il report JaCoCo o XCCov — identificare le classi rosse (non coperte). Priorità: logica di business → repository → ViewModel → componenti UI.

Strategia TDD

Il Test-Driven Development (TDD) garantisce automaticamente un'elevata copertura, poiché i test vengono scritti prima dell'implementazione. Il processo: rosso (scrivere un test che fallisce) → verde (scrivere il codice minimo) → refactoring. TDD disciplina lo sviluppatore, costringendolo a coprire casi limite e situazioni eccezionali che spesso rimangono senza test.

Test parametrizzati

Un test parametrizzato sostituisce decine di test ordinari. JUnit e XCTest supportano la parametrizzazione: @ParameterizedTest in JUnit 5, XCTestCase con testPerformanceExample in XCTest. La parametrizzazione consente di verificare molteplici dati di input senza duplicazione del codice, espandendo significativamente la copertura di rami e condizioni.

kotlin
// Test parametrizzato in Kotlin con 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)
}

Errori comuni con il Code Coverage

L'errore più comune è inseguire la percentuale senza analizzare la qualità dei test. Il team inizia a scrivere test per i test: verificare getter e setter, duplicare la copertura a diversi livelli, testare metodi banali. Questo dà una percentuale elevata ma non migliora la qualità reale.

Falso senso di sicurezza

Un Code Coverage elevato può creare la falsa sensazione che l'applicazione sia ben testata. Un test può eseguire una linea di codice ma non verificare la correttezza del risultato. Ad esempio: un test chiama un metodo di calcolo dello sconto ma non verifica l'importo — la linea viene eseguita, la copertura aumenta, ma il bug non viene trovato.

Ignorare i casi limite

Un errore tipico è testare solo il “percorso felice” (happy path) e ignorare i casi limite: liste vuote, valori null, numeri massimi, formati errati. È proprio ai limiti e alle eccezioni che si verificano la maggior parte dei bug. Branch coverage aiuta a identificare i rami mancati, ma non garantisce la verifica dei valori limite.

Mutation Testing — verifica della qualità dei test

Il Mutation Testing è un metodo per valutare la qualità dei test in cui vengono introdotte mutazioni (errori artificiali) nel codice sorgente e si verifica se i test falliscono. Pitest è un popolare strumento di mutation testing per Java e Kotlin. Se i test non falliscono su una mutazione, significa che non verificano quella condizione.

Principio di funzionamento di Pitest

Pitest crea mutanti — copie modificate del codice sorgente in cui, ad esempio, > viene sostituito con >=, true con false, o una chiamata a metodo viene rimossa. Quindi, per ogni mutante, vengono eseguiti i test. Se i test superano — il mutante è sopravvissuto, il che significa che i test non coprono quello scenario. Se i test falliscono — il mutante è stato ucciso, il test è valido.

groovy
// build.gradle — configurazione 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
}

Tipi di mutazione

Pitest supporta molti tipi di mutazione: modifica degli operatori condizionali (== → !=, < → <=), rimozione di chiamate a metodi, sostituzione dei valori di ritorno (true → false), modifica delle operazioni aritmetiche (+ → -), mutazione degli incrementi (i++ → i--). Più tipi di mutazione vengono uccisi dai test, più la suite di test è affidabile.

Obiettivo del Mutation Score

Il mutation score target è dell'80% o superiore. Ciò significa che l'80% degli errori artificiali viene rilevato dai test. Una copertura del codice (Code Coverage) del 90% non garantisce che i test trovino bug — il mutation testing fornisce una valutazione più obiettiva. Pitest può essere integrato nel CI come Quality Gate, bloccando il build se il mutation score scende sotto la soglia.

Integrazione del Code Coverage in CI/CD

Per il controllo automatico del Code Coverage in CI/CD, vengono utilizzati Quality Gate — valori soglia che, quando violati, contrassegnano il build come instabile o lo respingono. SonarQube consente di configurare un Quality Gate basato su una combinazione di metriche: copertura (≥80%), numero di bug, vulnerabilità e codice duplicato.

Configurazione del Quality Gate in GitHub Actions

In GitHub Actions, il Code Coverage viene integrato attraverso passaggi di azione: eseguire test con copertura → caricare il report su Codecov → verificare la soglia. Codecov commenta automaticamente le PR con il diff di copertura, mostrando quali linee sono cambiate e come ciò ha influenzato la percentuale complessiva. Se la copertura è diminuita, la PR viene bloccata fino a quando non vengono scritti test aggiuntivi.

yaml
# GitHub Actions — caricamento copertura su 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

Report e visualizzazione

I report HTML di JaCoCo e XCCov contengono evidenziazione visiva della copertura: verde — linee eseguite, rosso — non eseguite. SonarQube mostra inoltre la copertura a livello di file, classe, metodo e linea, nonché la cronologia delle modifiche della copertura per sprint. Ciò aiuta a prendere decisioni sul refactoring e l'aggiunta di test.

Domande frequenti

Quale percentuale di Code Coverage è considerata buona?

Per i progetti mobile, una copertura del 70–80% per la logica di business e del 50–60% per i componenti UI è considerata buona. Oltre l'80%, i costi dei test iniziano a superare i benefici. È importante ricordare che la percentuale non è un obiettivo ma un indicatore, e diversi moduli possono avere diversi livelli target.

Qual è la differenza tra Line e Branch Coverage?

Line Coverage mostra quante linee di codice sono state eseguite. Branch Coverage mostra quante ramificazioni (if-else, switch) sono state testate. Una linea con if può essere eseguita, ma potrebbe essere stato testato solo il ramo true e non il false. Branch Coverage è più rigorosa e rivela più scenari mancati.

Come integrare il Code Coverage in CI/CD?

In CI/CD, la copertura viene integrata tramite un Quality Gate: il build viene bloccato se la copertura è sotto la soglia. Per Android si usa JaCoCo + SonarQube; per iOS — xcodebuild -enableCodeCoverage con parsing di .xccovreport. GitHub Actions ha azioni pronte per Codecov.

Si può misurare la copertura per Jetpack Compose?

Sì, JaCoCo supporta Jetpack Compose attraverso il meccanismo standard di copertura JVM. Tuttavia, il codice Compose contiene molte espressioni lambda generate che JaCoCo potrebbe non coprire completamente. Si consiglia di escludere il codice Compose generato dal report tramite filtri.

Come evitare la falsa copertura?

La falsa copertura si verifica quando un test esegue codice ma non verifica il risultato. Soluzione: scrivere asserzioni per ogni scenario importante, utilizzare il mutation testing (Pitest) per verificare la qualità dei test, analizzare non solo la percentuale ma anche quali rami sono coperti.

Riepilogo

  • Code Coverage — metrica che mostra la percentuale di codice eseguito dai test, ma non garantisce l'assenza di bug
  • Line e Branch coverage — metriche principali; Branch è più rigorosa e rivela rami non testati
  • JaCoCo — strumento standard per Android, XCCov — per iOS, entrambi si integrano con Gradle e Xcode
  • Copertura target 70–80% per la logica di business — equilibrio ottimale tra qualità e costo
  • TDD e parametrizzazione — metodi efficaci per aumentare la copertura senza duplicare i test
  • SonarQube e Codecov — piattaforme per monitoraggio centralizzato e Quality Gates in CI/CD
  • Regola principale: non inseguire la percentuale, ma coprire i rischi critici e i casi limite

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche