Code Coverage în dezvoltarea mobilă: ce este, metrici și cum se măsoară

Autor: IT Sectr Publicat: 2026-04-09 Timp de citire: 9 min

Code Coverage (acoperirea codului) este o metrică care arată ce procent din codul sursă al aplicației este executat în timpul testării. Ajută la determinarea calității testelor, identificarea zonelor neverificate și prioritizarea scrierii de noi teste. Potrivit Atlassian, 2025, nivelul optim de acoperire este de 70–80% — peste acest prag, costurile testelor încep să depășească beneficiile.

Puncte cheie

  • Code Coverage — metrică ce măsoară procentul de cod executat de teste
  • Metricile de acoperire includ linii (line), ramuri (branch), funcții, condiții și căi
  • Instrumente: JaCoCo pentru Android, XCCov pentru iOS, SonarQube pentru analiza codului
  • Acoperirea țintă 70–80% — echilibrul între calitate și costul testelor
  • Integrarea CI/CD permite blocarea build-urilor la scăderea acoperirii sub prag

Ce este Code Coverage

Code Coverage (acoperirea codului) este o metrică cantitativă care determină ce parte din codul sursă al aplicației a fost executată în timpul testelor. Se exprimă în procente și se calculează ca raportul dintre numărul de linii/ramuri executate și numărul total. Acoperirea ridicată nu garantează absența bug-urilor, dar reduce riscul de erori omise.

De ce să măsurăm acoperirea

Acoperirea codului ajută echipa: să găsească zonele netestate ale codului, să ia decizii privind prioritățile scrierii testelor, să urmărească dinamica calității testării în CI/CD. În dezvoltarea mobilă, acoperirea este deosebit de importantă pentru logica de business, modelele de date și depozite — straturile cu cea mai mare probabilitate de erori.

Mituri despre Code Coverage

Un mit răspândit: „100% acoperire = calitate ideală”. În practică, 100% acoperire se atinge extrem de rar și adesea cu prețul unor teste superficiale. Acoperirea eficientă nu este o cursă pentru procent, ci o acoperire strategică a căilor critice și a condițiilor limită. Acoperirea nu spune nimic despre calitatea testelor în sine: un test poate trece, dar să nu verifice corectitudinea rezultatului.

Metrici de acoperire a codului

Există mai multe metrici Code Coverage, fiecare măsurând diferite aspecte ale testării. Line coverage (acoperirea liniilor) — cea mai simplă metrică, care arată procentul liniilor de cod executate. Branch coverage (acoperirea ramurilor) măsoară care ramificări if-else și switch au fost testate.

Acoperirea liniară (Line Coverage)

Line coverage numără fiecare linie de cod sursă ca executată sau nu. Dacă într-o linie se află un operator condițional sau o buclă, linia este considerată executată dacă controlul a ajuns la ea, chiar dacă nu toate ramurile au fost procesate. Este cea mai puțin strictă metrică, dar cea mai ușor de înțeles pentru evaluarea vizuală.

Acoperirea ramurilor (Branch Coverage)

Branch coverage evaluează dacă toate ramificările posibile din cod au fost testate. Pentru fiecare if-else se iau în considerare ambele ramuri: true și false. Pentru switch — fiecare case. Branch coverage este considerată o metrică mai strictă decât line coverage și identifică mai frecvent scenariile netestate.

MetricăCe măsoarăDificultatea atingerii
LineProcentul liniilor de cod executateScăzută
BranchProcentul ramificărilor executate (if/else, switch)Medie
FunctionProcentul funcțiilor și metodelor apelateScăzută
ConditionProcentul subexpresiilor logice (&&, ||)Ridicată

Acoperirea căilor (Path Coverage)

Path coverage — cea mai strictă metrică, care necesită verificarea tuturor combinațiilor posibile de ramificări dintr-o funcție. În practică, path coverage este rar folosită din cauza creșterii exponențiale a numărului de combinații: o funcție cu 10 ramificări are 1024 de căi posibile.

Instrumente de măsurare a acoperirii

În dezvoltarea mobilă se folosesc diverse instrumente pentru măsurarea Code Coverage în funcție de platformă. Pentru Android, standardul este JaCoCo (Java Code Coverage), care se integrează cu Gradle și suportă atât testele unitare, cât și testele instrumentale. Pentru iOS se folosește XCCov, încorporat în Xcode.

JaCoCo pentru Android

JaCoCo generează rapoarte în formate HTML, XML și CSV. Raportul HTML evidențiază vizual liniile: verde — executate, roșu — omise, galben — parțial executate. Raportul XML este compatibil cu SonarQube și alte sisteme de analiză a codului. JaCoCo suportă filtrarea claselor: se poate exclude codul generat, databinding, BuildConfig.

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

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

XCCov pentru iOS

XCCov — instrumentul încorporat al Xcode pentru măsurarea acoperirii codului. Se activează prin Gather coverage data în schema de testare. XCCov suportă acoperirea pentru Swift și Objective-C, generează rapoarte în .xccovreport și se integrează cu CI prin xcodebuild -enableCodeCoverage YES. Datele sunt afișate în consolă și pot fi exportate în JSON.

SonarQube și Codecov

Pentru monitorizarea centralizată a acoperirii se folosesc platforme: SonarQube (analiza calității codului + acoperire), Codecov și Coveralls. Aceste servicii agregă datele din JaCoCo și XCCov, arată tendințele, Quality Gate și integrarea cu GitHub/GitLab prin comentarii PR.

Cum să îmbunătățim acoperirea codului

Creșterea Code Coverage necesită o abordare sistematică: nu „atingem procentele”, ci acoperim riscurile. Primul pas este analiza raportului JaCoCo sau XCCov — identificarea claselor roșii (neacoperite). Prioritate: logica de business → depozite → ViewModel → componente UI.

Strategia TDD

Test-Driven Development (TDD) asigură automat o acoperire ridicată, deoarece testele se scriu înaintea implementării. Proces: roșu (scrie un test care eșuează) → verde (scrie codul minim) → refactorizare. TDD disciplinează dezvoltatorul, forțând acoperirea cazurilor limită și a situațiilor excepționale care rămân adesea netestate.

Teste parametrizate

Un singur test parametrizat înlocuiește zeci de teste obișnuite. JUnit și XCTest suportă parametrizarea: @ParameterizedTest în JUnit 5, XCTestCase cu testPerformanceExample în XCTest. Parametrizarea permite verificarea mai multor date de intrare fără duplicarea codului, ceea ce extinde semnificativ acoperirea ramurilor și condițiilor.

kotlin
// Test parametrizat în Kotlin cu 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)
}

Greșeli în lucrul cu Code Coverage

Cea mai frecventă greșeală — cursa după procent fără analiza calității testelor. Echipa începe să scrie teste de dragul testelor: verifică getter-e și setter-e, dublează acoperirea la diferite niveluri, testează metode triviale. Acest lucru dă un procent ridicat, dar nu crește calitatea reală.

Fals sentiment de siguranță

Un Code Coverage ridicat poate crea impresia iluzorie că aplicația este bine testată. Un test poate executa o linie de cod, dar să nu verifice corectitudinea rezultatului. De exemplu: testul apelează metoda de calcul a discountului, dar nu verifică suma — linia este executată, acoperirea crește, dar bug-ul nu este găsit.

Ignorarea cazurilor limită

Greșeala tipică — testarea doar a „căii fericite” (happy path) și ignorarea cazurilor limită: liste goale, valori null, numere maxime, formate incorecte. Majoritatea bug-urilor apar exact la limite și în excepții. Branch coverage ajută la identificarea ramurilor omise, dar nu garantează verificarea valorilor limită.

Mutation Testing — verificarea calității testelor

Mutation Testing este o metodă de evaluare a calității testelor în care se introduc mutații (erori artificiale) în codul sursă și se verifică dacă testele eșuează. Pitest — instrument popular de mutation testing pentru Java și Kotlin. Dacă testele nu au eșuat pe mutație — înseamnă că nu verifică acea condiție.

Principiul de funcționare al Pitest

Pitest creează mutanți — copii modificate ale codului sursă, în care, de exemplu, > este înlocuit cu >=, true cu false sau este eliminat un apel de metodă. Apoi pentru fiecare mutant se rulează testele. Dacă testele trec — mutantul a supraviețuit, înseamnă că testele nu acoperă acest scenariu. Dacă testele eșuează — mutantul a fost ucis, testul este corect.

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

Tipuri de mutații

Pitest suportă multiple tipuri de mutații: modificarea operatorilor condiționali (== → !=, < → <=), eliminarea apelurilor de metode, înlocuirea valorilor returnate (true → false), modificarea operațiilor aritmetice (+ → -), mutația incrementării (i++ → i--). Cu cât mai multe tipuri de mutații sunt ucise de teste, cu atât setul de teste este mai fiabil.

Scopul Mutation Score

Scorul de mutație țintă — 80% și peste. Aceasta înseamnă că 80% din erorile artificiale au fost detectate de teste. Acoperirea codului (Code Coverage) de 90% nu garantează că testele găsesc erori — mutation testing oferă o evaluare mai obiectivă. Pitest poate fi integrat în CI ca Quality Gate, blocând build-ul la scăderea scorului de mutație sub prag.

Integrarea Code Coverage în CI/CD

Pentru controlul automat al Code Coverage în CI/CD se folosesc Quality Gates — valori prag, la încălcarea cărora build-ul este marcat ca instabil sau respins. SonarQube permite configurarea Quality Gate pe baza unei combinații de metrici: acoperire (≥80%), numărul de bug-uri, vulnerabilități și cod duplicat.

Configurarea Quality Gate în GitHub Actions

În GitHub Actions, Code Coverage se integrează prin pași de acțiune: rularea testelor cu acoperire → încărcarea raportului în Codecov → verificarea pragului. Codecov comentează automat PR-ul cu diff-ul acoperirii, arătând care linii s-au schimbat și cum au afectat procentul general. Dacă acoperirea a scăzut — PR-ul este blocat până la scrierea de teste suplimentare.

yaml
# GitHub Actions — încărcarea acoperirii în 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

Raportare și vizualizare

Rapoartele HTML JaCoCo și XCCov conțin evidențierea vizuală a acoperirii: verde — linii executate, roșu — neexecutate. SonarQube arată suplimentar acoperirea la nivel de fișier, clasă, metodă și linie, precum și istoricul modificărilor acoperirii pe sprinturi. Acest lucru ajută la luarea deciziilor privind refactorizarea și adăugarea de teste.

Întrebări frecvente

Ce procent de Code Coverage este considerat bun?

Pentru proiectele mobile, o acoperire de 70–80% pentru logica de business și 50–60% pentru componentele UI este considerată bună. Peste 80%, costurile testării încep să depășească beneficiile. Este important să reținem că procentul nu este un scop, ci un indicator, iar diferite module pot avea niveluri țintă diferite.

Care este diferența dintre Line și Branch Coverage?

Line Coverage arată câte linii de cod au fost executate. Branch Coverage — câte ramificări (if-else, switch) au fost testate. O linie cu if poate fi executată, dar ramura true testată, iar false — nu. Branch Coverage este mai strict și identifică mai multe scenarii omise.

Cum se integrează Code Coverage în CI/CD?

În CI/CD, acoperirea se integrează prin Quality Gate: build-ul este blocat dacă acoperirea este sub prag. Pentru Android se folosește JaCoCo + SonarQube, pentru iOS — xcodebuild -enableCodeCoverage cu parsarea .xccovreport. GitHub Actions are acțiuni gata făcute pentru Codecov.

Se poate măsura acoperirea pentru Jetpack Compose?

Da, JaCoCo suportă Jetpack Compose prin mecanismul standard de acoperire JVM. Cu toate acestea, codul Compose conține multe expresii lambda generate pe care JaCoCo poate să nu le acopere complet. Se recomandă excluderea codului compose generat din raport prin filtre.

Cum se evită acoperirea falsă?

Acoperirea falsă apare atunci când testul execută codul, dar nu verifică rezultatul. Soluție: scrieți verificări assert pentru fiecare scenariu important, utilizați mutation testing (Pitest) pentru a verifica calitatea testelor, analizați nu doar procentul, ci și care ramuri sunt acoperite.

Concluzii

  • Code Coverage — metrică ce arată procentul de cod executat de teste, dar nu garantează absența bug-urilor
  • Line și Branch coverage — metrici principale; Branch este mai strict și identifică ramificări netestate
  • JaCoCo — instrument standard pentru Android, XCCov — pentru iOS, ambele se integrează cu Gradle și Xcode
  • Acoperirea țintă 70–80% pentru logica de business — echilibrul optim între calitate și cost
  • TDD și parametrizarea — metode eficiente de creștere a acoperirii fără duplicarea testelor
  • SonarQube și Codecov — platforme pentru monitorizare centralizată și Quality Gate în CI/CD
  • Regula principală: nu alerga după procent, ci acoperă riscurile critice și cazurile limită

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și