Code Coverage w rozwoju aplikacji mobilnych: co to jest, metryki i jak mierzyć

Autor: IT Sectr Opublikowano: 2026-04-09 Czas czytania: 9 min

Code Coverage (pokrycie kodu) to metryka pokazująca, jaki procent kodu źródłowego aplikacji jest wykonywany podczas testowania. Pomaga określić jakość testów, zidentyfikować niesprawdzone obszary i ustalić priorytety pisania nowych testów. Według Atlassian, 2025, optymalny poziom pokrycia wynosi 70–80% — powyżej tego progu koszty testów zaczynają przewyższać korzyści.

Najważniejsze

  • Code Coverage — metryka mierząca procent kodu wykonanego przez testy
  • Metryki pokrycia obejmują linie (line), gałęzie (branch), funkcje, warunki i ścieżki
  • Narzędzia: JaCoCo dla Android, XCCov dla iOS, SonarQube do analizy kodu
  • Docelowe pokrycie 70–80% — równowaga między jakością a kosztem testów
  • Integracja CI/CD pozwala blokować kompilacje przy spadku pokrycia poniżej progu

Co to jest Code Coverage

Code Coverage (pokrycie kodu) to ilościowa metryka, która określa, jaka część kodu źródłowego aplikacji została wykonana podczas testów. Wyrażana jest w procentach i obliczana jako stosunek liczby wykonanych linii/gałęzi do całkowitej liczby. Wysokie pokrycie nie gwarantuje braku błędów, ale zmniejsza ryzyko przeoczonych usterek.

Po co mierzyć pokrycie

Pokrycie kodu pomaga zespołowi: znajdować nieprzetestowane obszary kodu, podejmować decyzje o priorytetach pisania testów, śledzić dynamikę jakości testowania w CI/CD. W rozwoju aplikacji mobilnych pokrycie jest szczególnie ważne dla logiki biznesowej, modeli danych i repozytoriów — warstw, w których prawdopodobieństwo błędów jest najwyższe.

Mity o Code Coverage

Popularny mit: „100% pokrycia = idealna jakość“. W praktyce 100% pokrycia osiąga się niezwykle rzadko i często kosztem powierzchownych testów. Efektywne pokrycie to nie wyścig o procent, ale strategiczne pokrycie krytycznych ścieżek i warunków brzegowych. Pokrycie nie mówi nic o jakości samych testów: test może przechodzić, ale nie sprawdzać poprawności wyniku.

Metryki pokrycia kodu

Istnieje kilka metryk Code Coverage, z których każda mierzy różne aspekty testowania. Line coverage (pokrycie linii) to najprostsza metryka pokazująca procent wykonanych linii kodu. Branch coverage (pokrycie gałęzi) mierzy, które rozgałęzienia if-else i switch zostały przetestowane.

Pokrycie liniowe (Line Coverage)

Line coverage liczy każdą linię kodu źródłowego jako wykonaną lub nie. Jeśli w linii znajduje się operator warunkowy lub pętla, linia jest uznawana za wykonaną, jeśli sterowanie do niej dotarło, nawet jeśli nie wszystkie gałęzie zostały obsłużone. To najmniej rygorystyczna metryka, ale najbardziej zrozumiała do oceny wizualnej.

Pokrycie gałęzi (Branch Coverage)

Branch coverage ocenia, czy wszystkie możliwe rozgałęzienia w kodzie zostały przetestowane. Dla każdego if-else uwzględniane są obie gałęzie: true i false. Dla switch — każdy case. Branch coverage jest uznawana za bardziej rygorystyczną metrykę niż line coverage i częściej wykrywa niesprawdzone scenariusze.

MetrykaCo mierzyTrudność osiągnięcia
LineProcent wykonanych linii koduNiska
BranchProcent wykonanych rozgałęzień (if/else, switch)Średnia
FunctionProcent wywołanych funkcji i metodNiska
ConditionProcent logicznych podwyrażeń (&&, ||)Wysoka

Pokrycie ścieżek (Path Coverage)

Path coverage to najbardziej rygorystyczna metryka, wymagająca sprawdzenia wszystkich możliwych kombinacji rozgałęzień w funkcji. W praktyce path coverage jest rzadko używane ze względu na wykładniczy wzrost liczby kombinacji: funkcja z 10 rozgałęzieniami ma 1024 możliwych ścieżek.

Narzędzia do pomiaru pokrycia

W rozwoju aplikacji mobilnych stosuje się różne narzędzia do pomiaru Code Coverage w zależności od platformy. Dla Android standardem jest JaCoCo (Java Code Coverage), który integruje się z Gradle i obsługuje zarówno testy jednostkowe, jak i testy instrumentalne. Dla iOS używany jest XCCov, wbudowany w Xcode.

JaCoCo dla Android

JaCoCo generuje raporty w formatach HTML, XML i CSV. Raport HTML wizualnie podświetla linie: zielone — wykonane, czerwone — pominięte, żółte — częściowo wykonane. Raport XML jest kompatybilny z SonarQube i innymi systemami analizy kodu. JaCoCo obsługuje filtrowanie klas: można wykluczyć generated-kod, databinding, BuildConfig.

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

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

XCCov dla iOS

XCCov — wbudowane narzędzie Xcode do pomiaru pokrycia kodu. Włącza się przez Gather coverage data w schemacie testowania. XCCov obsługuje pokrycie dla Swift i Objective-C, generuje raporty w .xccovreport i integruje się z CI przez xcodebuild -enableCodeCoverage YES. Dane są wyświetlane w konsoli i mogą być eksportowane do JSON.

SonarQube i Codecov

Do scentralizowanego monitorowania pokrycia wykorzystuje się platformy: SonarQube (analiza jakości kodu + pokrycie), Codecov i Coveralls. Te serwisy agregują dane z JaCoCo i XCCov, pokazują trendy, Quality Gate i integrację z GitHub/GitLab przez komentarze PR.

Jak poprawić pokrycie kodu

Zwiększanie Code Coverage wymaga systematycznego podejścia: nie „dobić procentów”, ale zamykać ryzyka. Pierwszym krokiem jest analiza raportu JaCoCo lub XCCov — identyfikacja czerwonych (niepokrytych) klas. Priorytet: logika biznesowa → repozytoria → ViewModel → komponenty UI.

Strategia TDD

Test-Driven Development (TDD) automatycznie zapewnia wysokie pokrycie, ponieważ testy są pisane przed implementacją. Proces: czerwony (napisz test, który nie przechodzi) → zielony (napisz minimalny kod) → refaktoryzacja. TDD dyscyplinuje programistę, zmuszając do pokrycia przypadków brzegowych i wyjątków, które często pozostają bez testów.

Testy parametryzowane

Jeden test parametryzowany zastępuje dziesiątki zwykłych. JUnit i XCTest obsługują parametryzację: @ParameterizedTest w JUnit 5, XCTestCase z testPerformanceExample w XCTest. Parametryzacja pozwala sprawdzić wiele danych wejściowych bez duplikowania kodu, co znacznie rozszerza pokrycie gałęzi i warunków.

kotlin
// Test parametryzowany w Kotlin z 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)
}

Błędy przy pracy z Code Coverage

Najczęstszy błąd to wyścig o procent bez analizy jakości testów. Zespół zaczyna pisać testy dla testów: sprawdza gettery i settery, dubluje pokrycie na różnych poziomach, testuje trywialne metody. Daje to wysoki procent, ale nie podnosi rzeczywistej jakości.

Fałszywe poczucie bezpieczeństwa

Wysoki Code Coverage może stworzyć złudne wrażenie, że aplikacja jest dobrze przetestowana. Test może wykonać linię kodu, ale nie sprawdzić poprawności wyniku. Na przykład: test wywołuje metodę obliczania rabatu, ale nie sprawdza kwoty — linia wykonana, pokrycie rośnie, a błąd nie został znaleziony.

Ignorowanie przypadków brzegowych

Typowy błąd — testowanie tylko „szczęśliwej ścieżki“ (happy path) i ignorowanie przypadków brzegowych: pustych list, wartości null, maksymalnych liczb, nieprawidłowych formatów. To właśnie na granicach i wyjątkach występuje większość błędów. Branch coverage pomaga wykryć pominięte gałęzie, ale nie gwarantuje sprawdzenia wartości brzegowych.

Mutation Testing — sprawdzanie jakości testów

Mutation Testing to metoda oceny jakości testów, w której do kodu źródłowego wprowadza się mutacje (sztuczne błędy) i sprawdza, czy testy zawiodą. Pitest — popularne narzędzie mutation testing dla Java i Kotlin. Jeśli testy nie zawiodły na mutacji — oznacza to, że nie sprawdzają danego warunku.

Zasada działania Pitest

Pitest tworzy mutanty — zmodyfikowane kopie kodu źródłowego, w których na przykład > zastąpiono >=, true na false lub usunięto wywołanie metody. Następnie dla każdego mutanta uruchamiane są testy. Jeśli testy przechodzą — mutant przeżył, oznacza to, że testy nie pokrywają tego scenariusza. Jeśli testy zawodzą — mutant został zabity, test jest poprawny.

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

Rodzaje mutacji

Pitest obsługuje wiele rodzajów mutacji: zmiana operatorów warunkowych (== → !=, < → <=), usunięcie wywołań metod, zamiana zwracanych wartości (true → false), zmiana operacji arytmetycznych (+ → -), mutacja inkrementacji (i++ → i--). Im więcej rodzajów mutacji zostało zabitych przez testy, tym bardziej niezawodny zestaw testów.

Cel Mutation Score

Docelowy mutation score — 80% i więcej. Oznacza to, że 80% sztucznych błędów zostało wykrytych przez testy. Pokrycie kodu (Code Coverage) na poziomie 90% nie gwarantuje, że testy znajdują błędy — mutation testing daje bardziej obiektywną ocenę. Pitest może być zintegrowany z CI jako Quality Gate, blokując kompilację przy spadku mutation score poniżej progu.

Integracja Code Coverage z CI/CD

Do automatycznej kontroli Code Coverage w CI/CD stosuje się Quality Gates — wartości progowe, przy przekroczeniu których kompilacja jest oznaczana jako niestabilna lub odrzucana. SonarQube pozwala skonfigurować Quality Gate na podstawie kombinacji metryk: pokrycie (≥80%), liczba błędów, podatności i zduplikowanego kodu.

Konfiguracja Quality Gate w GitHub Actions

W GitHub Actions Code Coverage integruje się przez kroki akcji: uruchomienie testów z pokryciem → przesłanie raportu do Codecov → sprawdzenie progu. Codecov automatycznie komentuje PR z diffem pokrycia, pokazując, które linie się zmieniły i jak to wpłynęło na ogólny procent. Jeśli pokrycie spadło — PR jest blokowany do czasu napisania dodatkowych testów.

yaml
# GitHub Actions — przesyłanie pokrycia do 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

Raportowanie i wizualizacja

Raporty HTML JaCoCo i XCCov zawierają wizualne podświetlenie pokrycia: zielony — wykonane linie, czerwony — niewykonane. SonarQube dodatkowo pokazuje pokrycie na poziomie pliku, klasy, metody i linii, a także historię zmian pokrycia w sprintach. Pomaga to podejmować decyzje o refaktoryzacji i dodawaniu testów.

Często zadawane pytania

Jaki procent Code Coverage uważa się za dobry?

Dla projektów mobilnych za dobre uważa się pokrycie 70–80% dla logiki biznesowej i 50–60% dla komponentów UI. Powyżej 80% koszty testowania zaczynają przewyższać korzyści. Ważne jest, aby pamiętać, że procent nie jest celem, ale wskaźnikiem, a różne moduły mogą mieć różne docelowe poziomy.

Jaka jest różnica między Line a Branch Coverage?

Line Coverage pokazuje, ile linii kodu zostało wykonanych. Branch Coverage — ile rozgałęzień (if-else, switch) zostało przetestowanych. Linia z if może być wykonana, ale gałąź true przetestowana, a false — nie. Branch Coverage jest bardziej rygorystyczny i wykrywa więcej pominiętych scenariuszy.

Jak zintegrować Code Coverage z CI/CD?

W CI/CD pokrycie integruje się przez Quality Gate: kompilacja jest blokowana, jeśli pokrycie jest poniżej progu. Dla Android używa się JaCoCo + SonarQube, dla iOS — xcodebuild -enableCodeCoverage z parsowaniem .xccovreport. GitHub Actions ma gotowe akcje dla Codecov.

Czy można zmierzyć pokrycie dla Jetpack Compose?

Tak, JaCoCo obsługuje Jetpack Compose przez standardowy mechanizm pokrycia JVM. Jednak kod Compose zawiera wiele wygenerowanych wyrażeń lambda, które JaCoCo może nie w pełni pokrywać. Zaleca się wykluczanie wygenerowanego kodu compose z raportu przez filtry.

Jak uniknąć fałszywego pokrycia?

Fałszywe pokrycie powstaje, gdy test wykonuje kod, ale nie sprawdza wyniku. Rozwiązanie: pisać assercje dla każdego ważnego scenariusza, używać mutation testing (Pitest) do sprawdzenia jakości testów, analizować nie tylko procent, ale także które gałęzie są pokryte.

Podsumowanie

  • Code Coverage — metryka pokazująca procent kodu wykonanego przez testy, ale nie gwarantująca braku błędów
  • Line i Branch coverage — podstawowe metryki; Branch jest bardziej rygorystyczny i wykrywa nieprzetestowane rozgałęzienia
  • JaCoCo — standardowe narzędzie dla Android, XCCov — dla iOS, oba integrują się z Gradle i Xcode
  • Docelowe pokrycie 70–80% dla logiki biznesowej — optymalna równowaga między jakością a kosztem
  • TDD i parametryzacja — efektywne metody zwiększania pokrycia bez duplikowania testów
  • SonarQube i Codecov — platformy do scentralizowanego monitorowania i Quality Gate w CI/CD
  • Główna zasada: nie gonić za procentem, ale pokrywać krytyczne ryzyka i przypadki brzegowe

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również