Code Coverage (Codeabdeckung) ist eine Metrik, die zeigt, wie viel Prozent des Quellcodes einer Anwendung während des Testens ausgeführt werden. Sie hilft, die Testqualität zu bestimmen, ungeprüfte Bereiche zu identifizieren und das Schreiben neuer Tests zu priorisieren. Laut Atlassian, 2025 liegt der optimale Abdeckungsgrad bei 70–80 % — oberhalb dieser Schwelle übersteigen die Testkosten den Nutzen.
Wichtige Erkenntnisse
Code Coverage (Codeabdeckung) ist eine quantitative Metrik, die bestimmt, welcher Teil des Quellcodes der Anwendung während der Tests ausgeführt wurde. Sie wird in Prozent ausgedrückt und als Verhältnis der ausgeführten Zeilen/Zweige zur Gesamtzahl berechnet. Eine hohe Abdeckung garantiert keine fehlerfreie Software, reduziert jedoch das Risiko übersehener Fehler.
Die Codeabdeckung hilft dem Team: ungetestete Codebereiche zu finden, Entscheidungen über Prioritäten beim Schreiben von Tests zu treffen und die Dynamik der Testqualität in CI/CD zu verfolgen. In der mobilen Entwicklung ist die Abdeckung besonders wichtig für Geschäftslogik, Datenmodelle und Repositories — Schichten, in denen die Fehlerwahrscheinlichkeit am höchsten ist.
Ein verbreiteter Mythos: „100 % Abdeckung = perfekte Qualität“. In der Praxis ist eine 100%ige Abdeckung äußerst selten und wird oft auf Kosten oberflächlicher Tests erreicht. Effektive Abdeckung ist kein Wettlauf um Prozente, sondern eine strategische Abdeckung kritischer Pfade und Grenzfälle. Die Abdeckung sagt nichts über die Qualität der Tests selbst aus: Ein Test kann bestehen, aber die Korrektheit des Ergebnisses nicht überprüfen.
Es gibt mehrere Code-Coverage-Metriken, die jeweils verschiedene Aspekte des Testens messen. Line Coverage (Zeilenabdeckung) ist die einfachste Metrik und zeigt den Prozentsatz der ausgeführten Codezeilen. Branch Coverage (Zweigabdeckung) misst, welche if-else- und switch-Verzweigungen getestet wurden.
Line Coverage zählt jede Quellcodezeile als ausgeführt oder nicht ausgeführt. Enthält eine Zeile einen bedingten Operator oder eine Schleife, gilt die Zeile als ausgeführt, wenn die Steuerung sie erreicht hat, auch wenn nicht alle Zweige verarbeitet wurden. Dies ist die am wenigsten strenge Metrik, aber für die visuelle Bewertung am verständlichsten.
Branch Coverage bewertet, ob alle möglichen Zweige im Code getestet wurden. Für jedes if-else werden beide Zweige berücksichtigt: true und false. Für switch wird jeder case berücksichtigt. Branch Coverage gilt als strengere Metrik als Line Coverage und deckt häufiger ungetestete Szenarien auf.
| Metrik | Was sie misst | Schwierigkeitsgrad |
|---|---|---|
| Line | Prozentsatz ausgeführter Codezeilen | Niedrig |
| Branch | Prozentsatz ausgeführter Zweige (if/else, switch) | Mittel |
| Function | Prozentsatz aufgerufener Funktionen und Methoden | Niedrig |
| Condition | Prozentsatz logischer Unterausdrücke (&&, ||) | Hoch |
Path Coverage ist die strengste Metrik und erfordert die Überprüfung aller möglichen Kombinationen von Zweigen in einer Funktion. In der Praxis wird Path Coverage aufgrund des exponentiellen Wachstums der Anzahl von Kombinationen selten verwendet: Eine Funktion mit 10 Zweigen hat 1024 mögliche Pfade.
In der mobilen Entwicklung werden je nach Plattform verschiedene Tools zur Messung der Code Coverage verwendet. Für Android ist der Standard JaCoCo (Java Code Coverage), das sich in Gradle integriert und sowohl Unit-Tests als auch Instrumentierungstests unterstützt. Für iOS wird XCCov verwendet, das in Xcode integriert ist.
JaCoCo erstellt Berichte in den Formaten HTML, XML und CSV. Der HTML-Bericht hebt Zeilen visuell hervor: grün — ausgeführt, rot — übersprungen, gelb — teilweise ausgeführt. Der XML-Bericht ist mit SonarQube und anderen Code-Analyse-Systemen kompatibel. JaCoCo unterstützt Klassenfilterung: generierter Code, Data Binding und BuildConfig können ausgeschlossen werden.
// build.gradle — JaCoCo-Konfiguration
android {
buildTypes {
debug {
testCoverageEnabled = true
}
}
}
// JaCoCo-Bericht erstellen
task jacocoTestReport(type: JacocoReport) {
dependsOn 'testDebugUnitTest'
reports {
xml.enabled = true
html.enabled = true
}
}
XCCov ist ein in Xcode integriertes Tool zur Messung der Codeabdeckung. Es wird über Gather coverage data im Testschema aktiviert. XCCov unterstützt die Abdeckung für Swift und Objective-C, erstellt Berichte im .xccovreport-Format und integriert sich über xcodebuild -enableCodeCoverage YES in CI. Daten werden auf der Konsole ausgegeben und können in JSON exportiert werden.
Für die zentrale Überwachung der Abdeckung werden Plattformen wie SonarQube (Codequalitätsanalyse + Abdeckung), Codecov und Coveralls verwendet. Diese Dienste aggregieren Daten von JaCoCo und XCCov, zeigen Trends, Quality Gates und Integration mit GitHub/GitLab über PR-Kommentare.
Die Verbesserung der Code Coverage erfordert einen systematischen Ansatz: nicht „Prozentzahlen erhöhen“, sondern Risiken abdecken. Der erste Schritt ist die Analyse des JaCoCo- oder XCCov-Berichts — Identifizierung roter (nicht abgedeckter) Klassen. Priorität: Geschäftslogik → Repositories → ViewModel → UI-Komponenten.
Test-Driven Development (TDD) stellt automatisch eine hohe Abdeckung sicher, da Tests vor der Implementierung geschrieben werden. Der Prozess: rot (fehlschlagenden Test schreiben) → grün (minimalen Code schreiben) → Refactoring. TDD diszipliniert den Entwickler und zwingt ihn, Grenzfälle und Ausnahmesituationen abzudecken, die oft ungetestet bleiben.
Ein parametrisierter Test ersetzt Dutzende gewöhnlicher Tests. JUnit und XCTest unterstützen Parametrisierung: @ParameterizedTest in JUnit 5, XCTestCase mit testPerformanceExample in XCTest. Die Parametrisierung ermöglicht die Überprüfung vieler Eingabedaten ohne Code-Duplizierung, was die Zweig- und Bedingungsabdeckung erheblich erweitert.
// Parametrisierter Test in Kotlin mit 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)
}
Der häufigste Fehler ist die Jagd nach der Prozentzahl ohne Analyse der Testqualität. Das Team beginnt, Tests um der Tests willen zu schreiben: getter und setter prüfen, Abdeckung auf verschiedenen Ebenen duplizieren, triviale Methoden testen. Dies ergibt eine hohe Prozentzahl, verbessert aber nicht die tatsächliche Qualität.
Eine hohe Code Coverage kann ein falsches Gefühl vermitteln, dass die Anwendung gut getestet ist. Ein Test kann eine Codezeile ausführen, aber die Korrektheit des Ergebnisses nicht überprüfen. Beispiel: Ein Test ruft eine Rabattberechnungsmethode auf, überprüft aber nicht den Betrag — die Zeile wird ausgeführt, die Abdeckung steigt, aber der Fehler wird nicht gefunden.
Ein typischer Fehler ist es, nur den „Happy Path“ zu testen und Grenzfälle zu ignorieren: leere Listen, Nullwerte, Maximalzahlen, ungültige Formate. Die meisten Fehler treten an Grenzen und Ausnahmen auf. Branch Coverage hilft, übersehene Zweige zu identifizieren, garantiert aber nicht die Überprüfung von Grenzwerten.
Mutation Testing ist eine Methode zur Bewertung der Testqualität, bei der Mutationen (künstliche Fehler) in den Quellcode eingefügt und geprüft wird, ob die Tests fehlschlagen. Pitest ist ein beliebtes Mutation-Testing-Tool für Java und Kotlin. Wenn Tests bei einer Mutation nicht fehlschlagen, überprüfen sie diese Bedingung nicht.
Pitest erstellt Mutanten — modifizierte Kopien des Quellcodes, bei denen beispielsweise > durch >=, true durch false ersetzt oder ein Methodenaufruf entfernt wird. Dann werden für jeden Mutanten die Tests ausgeführt. Wenn die Tests bestehen — hat der Mutant überlebt, was bedeutet, dass die Tests dieses Szenario nicht abdecken. Wenn die Tests fehlschlagen — wurde der Mutant getötet, der Test ist gültig.
// build.gradle — Pitest-Konfiguration
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 unterstützt viele Mutationsarten: Änderung bedingter Operatoren (== → !=, < → <=), Entfernen von Methodenaufrufen, Ersetzen von Rückgabewerten (true → false), Änderung arithmetischer Operationen (+ → -), Mutation von Inkrementen (i++ → i--). Je mehr Mutationsarten von den Tests getötet werden, desto zuverlässiger ist die Testsammlung.
Der angestrebte Mutation Score liegt bei 80 % oder höher. Das bedeutet, dass 80 % der künstlichen Fehler von den Tests erkannt werden. Eine Code Coverage von 90 % garantiert nicht, dass Tests Fehler finden — Mutation Testing liefert eine objektivere Bewertung. Pitest kann als Quality Gate in CI integriert werden und den Build blockieren, wenn der Mutation Score unter die Schwelle fällt.
Für die automatische Steuerung der Code Coverage in CI/CD werden Quality Gates verwendet — Schwellenwerte, bei deren Verletzung der Build als instabil markiert oder abgelehnt wird. SonarQube ermöglicht die Konfiguration eines Quality Gates basierend auf einer Kombination von Metriken: Abdeckung (≥80 %), Anzahl der Fehler, Sicherheitslücken und doppelter Code.
In GitHub Actions wird Code Coverage durch Aktionsschritte integriert: Tests mit Abdeckung ausführen → Bericht an Codecov hochladen → Schwelle prüfen. Codecov kommentiert automatisch PRs mit dem Abdeckungsdiff und zeigt, welche Zeilen sich geändert haben und wie sich dies auf den Gesamtprozentsatz ausgewirkt hat. Wenn die Abdeckung gefallen ist, wird der PR blockiert, bis zusätzliche Tests geschrieben werden.
# GitHub Actions — Coverage zu Codecov hochladen
- 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
HTML-Berichte von JaCoCo und XCCov enthalten visuelle Hervorhebungen der Abdeckung: grün — ausgeführte Zeilen, rot — nicht ausgeführte. SonarQube zeigt zusätzlich die Abdeckung auf Datei-, Klassen-, Methoden- und Zeilenebene sowie den Verlauf der Abdeckungsänderungen über Sprints. Dies hilft bei Entscheidungen über Refactoring und das Hinzufügen von Tests.
Häufig gestellte Fragen
Für Mobilprojekte gilt eine Abdeckung von 70–80 % für die Geschäftslogik und 50–60 % für UI-Komponenten als gut. Über 80 % hinaus beginnen die Testkosten den Nutzen zu übersteigen. Es ist wichtig zu bedenken, dass der Prozentsatz kein Ziel, sondern ein Indikator ist, und verschiedene Module können unterschiedliche Zielniveaus haben.
Line Coverage zeigt, wie viele Codezeilen ausgeführt wurden. Branch Coverage zeigt, wie viele Verzweigungen (if-else, switch) getestet wurden. Eine Zeile mit if kann ausgeführt sein, aber möglicherweise wurde nur der true-Zweig getestet, nicht der false-Zweig. Branch Coverage ist strenger und deckt mehr übersehene Szenarien auf.
In CI/CD wird die Abdeckung über ein Quality Gate integriert: Der Build wird blockiert, wenn die Abdeckung unter der Schwelle liegt. Für Android wird JaCoCo + SonarQube verwendet, für iOS — xcodebuild -enableCodeCoverage mit .xccovreport-Parsing. GitHub Actions hat vorgefertigte Aktionen für Codecov.
Ja, JaCoCo unterstützt Jetpack Compose über den standardmäßigen JVM-Abdeckungsmechanismus. Allerdings enthält Compose-Code viele generierte Lambda-Ausdrücke, die JaCoCo möglicherweise nicht vollständig abdeckt. Es wird empfohlen, generierten Compose-Code über Filter aus dem Bericht auszuschließen.
Falsche Abdeckung tritt auf, wenn ein Test Code ausführt, aber das Ergebnis nicht überprüft. Lösung: Assert-Prüfungen für jedes wichtige Szenario schreiben, Mutation Testing (Pitest) zur Überprüfung der Testqualität verwenden, nicht nur den Prozentsatz, sondern auch welche Zweige abgedeckt sind, analysieren.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch