Το Code Coverage (κάλυψη κώδικα) είναι μια μετρική που δείχνει πόσο τοις εκατό του πηγαίου κώδικα της εφαρμογής εκτελείται κατά τη διάρκεια των δοκιμών. Βοηθά στον προσδιορισμό της ποιότητας των δοκιμών, στον εντοπισμό μη ελεγμένων τμημάτων και στην ιεράρχηση προτεραιοτήτων για τη σύνταξη νέων δοκιμών. Σύμφωνα με τα δεδομένα Atlassian, 2025, το βέλτιστο επίπεδο κάλυψης είναι 70–80% — πάνω από αυτό το όριο, το κόστος των δοκιμών αρχίζει να υπερβαίνει το όφελος.
Βασικά σημεία
Code Coverage (κάλυψη κώδικα) είναι μια ποσοτική μετρική που καθορίζει ποιο μέρος του πηγαίου κώδικα της εφαρμογής εκτελέστηκε κατά τη διάρκεια των δοκιμών. Εκφράζεται σε ποσοστά και υπολογίζεται ως η αναλογία του αριθμού των εκτελεσμένων γραμμών/κλάδων προς το σύνολο. Η υψηλή κάλυψη δεν εγγυάται την απουσία σφαλμάτων, αλλά μειώνει τον κίνδυνο παραβλεπόμενων λαθών.
Η κάλυψη κώδικα βοηθά την ομάδα: να βρει μη ελεγμένα τμήματα κώδικα, να λάβει αποφάσεις σχετικά με προτεραιότητες σύνταξης δοκιμών, να παρακολουθεί τη δυναμική της ποιότητας των δοκιμών στο CI/CD. Στην ανάπτυξη εφαρμογών για κινητά, η κάλυψη είναι ιδιαίτερα σημαντική για την επιχειρηματική λογική, τα μοντέλα δεδομένων και τα αποθετήρια — επίπεδα όπου η πιθανότητα σφαλμάτων είναι υψηλότερη.
Ένας διαδεδομένος μύθος: “100% κάλυψη = ιδανική ποιότητα”. Στην πράξη, η 100% κάλυψη επιτυγχάνεται εξαιρετικά σπάνια και συχνά με κόστος επιφανειακών δοκιμών. Αποτελεσματική κάλυψη — δεν είναι αγώνας για το ποσοστό, αλλά στρατηγική κάλυψη κρίσιμων διαδρομών και οριακών συνθηκών. Η κάλυψη δεν λέει τίποτα για την ποιότητα των ίδιων των δοκιμών: μια δοκιμή μπορεί να περάσει αλλά να μην ελέγχει την ορθότητα του αποτελέσματος.
Υπάρχουν αρκετές μετρικές Code Coverage, καθεμία από τις οποίες μετρά διαφορετικές πτυχές των δοκιμών. Line coverage (κάλυψη γραμμών) — η απλούστερη μετρική που δείχνει το ποσοστό των εκτελεσμένων γραμμών κώδικα. Branch coverage (κάλυψη κλάδων) μετρά ποιοι κλάδοι if-else και switch έχουν ελεγχθεί.
Το Line coverage μετρά κάθε γραμμή πηγαίου κώδικα ως εκτελεσμένη ή όχι. Εάν σε μια γραμμή υπάρχει τελεστής συνθήκης ή βρόχος, η γραμμή θεωρείται εκτελεσμένη εάν ο έλεγχος έφτασε σε αυτήν, ακόμη και αν δεν έχουν υποστεί επεξεργασία όλοι οι κλάδοι. Αυτή είναι η λιγότερο αυστηρή μετρική, αλλά η πιο κατανοητή για οπτική αξιολόγηση.
Το Branch coverage αξιολογεί εάν όλοι οι πιθανοί κλάδοι στον κώδικα έχουν ελεγχθεί. Για κάθε if-else λαμβάνονται υπόψη και οι δύο κλάδοι: true και false. Για switch — κάθε case. Το Branch coverage θεωρείται πιο αυστηρή μετρική από το line coverage και εντοπίζει συχνότερα μη ελεγμένα σενάρια.
| Μετρική | Τι μετρά | Δυσκολία επίτευξης |
|---|---|---|
| Line | Ποσοστό εκτελεσμένων γραμμών κώδικα | Χαμηλή |
| Branch | Ποσοστό εκτελεσμένων κλάδων (if/else, switch) | Μέτρια |
| Function | Ποσοστό κληθέντων συναρτήσεων και μεθόδων | Χαμηλή |
| Condition | Ποσοστό λογικών υπο-εκφράσεων (&&, ||) | Υψηλή |
Path coverage — η πιο αυστηρή μετρική που απαιτεί έλεγχο όλων των πιθανών συνδυασμών κλάδων σε μια συνάρτηση. Στην πράξη, το path coverage χρησιμοποιείται σπάνια λόγω της εκθετικής αύξησης του αριθμού των συνδυασμών: μια συνάρτηση με 10 κλάδους έχει 1024 πιθανά μονοπάτια.
Στην ανάπτυξη εφαρμογών για κινητά, χρησιμοποιούνται διάφορα εργαλεία για τη μέτρηση του Code Coverage ανάλογα με την πλατφόρμα. Για Android, το πρότυπο είναι το JaCoCo (Java Code Coverage), το οποίο ενσωματώνεται με το Gradle και υποστηρίζει τόσο μοναδιαίες δοκιμές όσο και δοκιμές οργάνων. Για iOS, χρησιμοποιείται το XCCov, ενσωματωμένο στο Xcode.
Το JaCoCo δημιουργεί αναφορές σε μορφές HTML, XML και CSV. Η αναφορά HTML τονίζει οπτικά τις γραμμές: πράσινο — εκτελεσμένες, κόκκινο — παραλειφθείσες, κίτρινο — μερικώς εκτελεσμένες. Η αναφορά XML είναι συμβατή με το SonarQube και άλλα συστήματα ανάλυσης κώδικα. Το JaCoCo υποστηρίζει φιλτράρισμα κλάσεων: μπορεί να εξαιρεθεί generated κώδικας, databinding, BuildConfig.
// build.gradle — ρύθμιση JaCoCo
android {
buildTypes {
debug {
testCoverageEnabled = true
}
}
}
// Δημιουργία αναφοράς JaCoCo
task jacocoTestReport(type: JacocoReport) {
dependsOn 'testDebugUnitTest'
reports {
xml.enabled = true
html.enabled = true
}
}
Το XCCov — ενσωματωμένο εργαλείο του Xcode για τη μέτρηση της κάλυψης κώδικα. Ενεργοποιείται μέσω του Gather coverage data στο σχήμα δοκιμών. Το XCCov υποστηρίζει κάλυψη για Swift και Objective-C, δημιουργεί αναφορές σε .xccovreport και ενσωματώνεται με το CI μέσω xcodebuild -enableCodeCoverage YES. Τα δεδομένα εμφανίζονται στην κονσόλα και μπορούν να εξαχθούν σε JSON.
Για κεντρική παρακολούθηση της κάλυψης χρησιμοποιούνται πλατφόρμες: SonarQube (ανάλυση ποιότητας κώδικα + κάλυψη), Codecov και Coveralls. Αυτές οι υπηρεσίες συγκεντρώνουν δεδομένα από το JaCoCo και το XCCov, εμφανίζουν τάσεις, Quality Gate και ενσωμάτωση με GitHub/GitLab μέσω σχολίων PR.
Η αύξηση του Code Coverage απαιτεί συστηματική προσέγγιση: όχι “να χτυπήσετε τα ποσοστά”, αλλά να καλύψετε τους κινδύνους. Το πρώτο βήμα είναι η ανάλυση της αναφοράς JaCoCo ή XCCov — εντοπισμός των κόκκινων (μη καλυμμένων) κλάσεων. Προτεραιότητα: επιχειρηματική λογική → αποθετήρια → ViewModel → στοιχεία UI.
Το Test-Driven Development (TDD) εξασφαλίζει αυτόματα υψηλή κάλυψη, επειδή οι δοκιμές γράφονται πριν από την υλοποίηση. Διαδικασία: κόκκινο (γράψτε μια δοκιμή που αποτυγχάνει) → πράσινο (γράψτε τον ελάχιστο κώδικα) → ανακατασκευή. TDD πειθαρχεί τον προγραμματιστή, αναγκάζοντάς τον να καλύπτει οριακές περιπτώσεις και εξαιρετικές καταστάσεις που συχνά μένουν χωρίς δοκιμές.
Μία παραμετροποιημένη δοκιμή αντικαθιστά δεκάδες συνηθισμένες. Τα JUnit και XCTest υποστηρίζουν παραμετροποίηση: @ParameterizedTest στο JUnit 5, XCTestCase με testPerformanceExample στο XCTest. Η παραμετροποίηση επιτρέπει τον έλεγχο πολλαπλών εισόδων χωρίς διπλασιασμό κώδικα, γεγονός που επεκτείνει σημαντικά την κάλυψη κλάδων και συνθηκών.
// Παραμετροποιημένη δοκιμή σε Kotlin με 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)
}
Το πιο συνηθισμένο λάθος — κυνήγι του ποσοστού χωρίς ανάλυση της ποιότητας των δοκιμών. Η ομάδα αρχίζει να γράφει δοκιμές για χάρη των δοκιμών: ελέγχει getters και setters, διπλασιάζει την κάλυψη σε διαφορετικά επίπεδα, δοκιμάζει τετριμμένες μεθόδους. Αυτό δίνει υψηλό ποσοστό αλλά δεν αυξάνει την πραγματική ποιότητα.
Το υψηλό Code Coverage μπορεί να δημιουργήσει την ψευδή εντύπωση ότι η εφαρμογή έχει δοκιμαστεί καλά. Μια δοκιμή μπορεί να εκτελέσει μια γραμμή κώδικα αλλά να μην ελέγξει την ορθότητα του αποτελέσματος. Για παράδειγμα: η δοκιμή καλεί μια μέθοδο υπολογισμού έκπτωσης, αλλά δεν ελέγχει το ποσό — η γραμμή εκτελείται, η κάλυψη αυξάνεται, αλλά το σφάλμα δεν βρέθηκε.
Τυπικό λάθος — δοκιμή μόνο του “ευτυχισμένου μονοπατιού” (happy path) και παραβλεψη οριακών περιπτώσεων: κενές λίστες, τιμές null, μέγιστοι αριθμοί, λανθασμένες μορφές. Τα περισσότερα σφάλματα συμβαίνουν ακριβώς στα όρια και στις εξαιρέσεις. Το Branch coverage βοηθά στον εντοπισμό παραλειφθέντων κλάδων, αλλά δεν εγγυάται τον έλεγχο οριακών τιμών.
Το Mutation Testing είναι μια μέθοδος αξιολόγησης της ποιότητας των δοκιμών κατά την οποία εισάγονται μεταλλάξεις (τεχνητά σφάλματα) στον πηγαίο κώδικα και ελέγχεται αν οι δοκιμές αποτυγχάνουν. Pitest — δημοφιλές εργαλείο mutation testing για Java και Kotlin. Αν οι δοκιμές δεν απέτυχαν στη μετάλλαξη — σημαίνει ότι δεν ελέγχουν αυτή τη συνθήκη.
Το Pitest δημιουργεί μεταλλάκτες — τροποποιημένα αντίγραφα του πηγαίου κώδικα, στα οποία, για παράδειγμα, το > αντικαταστάθηκε με >=, το true με false, ή αφαιρέθηκε μια κλήση μεθόδου. Στη συνέχεια, για κάθε μεταλλάκτη εκτελούνται οι δοκιμές. Αν οι δοκιμές περάσουν — ο μεταλλάκτης επέζησε, πράγμα που σημαίνει ότι οι δοκιμές δεν καλύπτουν αυτό το σενάριο. Αν οι δοκιμές αποτύχουν — ο μεταλλάκτης σκοτώθηκε, η δοκιμή είναι σωστή.
// build.gradle — ρύθμιση 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 υποστηρίζει πολλούς τύπους μεταλλάξεων: αλλαγή τελεστών συνθήκης (== → !=, < → <=), αφαίρεση κλήσεων μεθόδων, αντικατάσταση επιστρεφόμενων τιμών (true → false), αλλαγή αριθμητικών πράξεων (+ → -), μετάλλαξη αύξησης (i++ → i--). Όσο περισσότεροι τύποι μεταλλάξεων σκοτώνονται από τις δοκιμές, τόσο πιο αξιόπιστο είναι το σύνολο δοκιμών.
Στόχος mutation score — 80% και άνω. Αυτό σημαίνει ότι το 80% των τεχνητών σφαλμάτων έχουν εντοπιστεί από τις δοκιμές. Η κάλυψη κώδικα (Code Coverage) 90% δεν εγγυάται ότι οι δοκιμές βρίσκουν σφάλματα — το mutation testing δίνει μια πιο αντικειμενική αξιολόγηση. Pitest μπορεί να ενσωματωθεί στο CI ως Quality Gate, μπλοκάροντας το build όταν το mutation score πέσει κάτω από το όριο.
Για τον αυτόματο έλεγχο του Code Coverage στο CI/CD χρησιμοποιούνται Quality Gates — τιμές κατωφλίου, κατά παράβαση των οποίων το build επισημαίνεται ως ασταθές ή απορρίπτεται. SonarQube επιτρέπει τη διαμόρφωση του Quality Gate βάσει συνδυασμού μετρικών: κάλυψη (≥80%), αριθμός σφαλμάτων, τρωτότητες και διπλότυπος κώδικας.
Στο GitHub Actions, το Code Coverage ενσωματώνεται μέσω βημάτων ενέργειας: εκτέλεση δοκιμών με κάλυψη → μεταφόρτωση αναφοράς στο Codecov → έλεγχος κατωφλίου. Codecov σχολιάζει αυτόματα το PR με τη διαφορά κάλυψης, δείχνοντας ποιες γραμμές άλλαξαν και πώς αυτό επηρέασε το συνολικό ποσοστό. Αν η κάλυψη μειώθηκε — το PR μπλοκάρεται μέχρι τη σύνταξη πρόσθετων δοκιμών.
# GitHub Actions — μεταφόρτωση κάλυψης στο 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
Οι αναφορές HTML των JaCoCo και XCCov περιέχουν οπτική επισήμανση κάλυψης: πράσινο — εκτελεσμένες γραμμές, κόκκινο — μη εκτελεσμένες. SonarQube επιπλέον δείχνει την κάλυψη σε επίπεδο αρχείου, κλάσης, μεθόδου και γραμμής, καθώς και το ιστορικό αλλαγών κάλυψης ανά sprint. Αυτό βοηθά στη λήψη αποφάσεων σχετικά με την ανακατασκευή και την προσθήκη δοκιμών.
Συχνές Ερωτήσεις
Για κινητά έργα, η κάλυψη 70–80% για την επιχειρηματική λογική και 50–60% για τα στοιχεία UI θεωρείται καλή. Πάνω από 80%, το κόστος των δοκιμών αρχίζει να υπερβαίνει το όφελος. Είναι σημαντικό να θυμάστε ότι το ποσοστό δεν είναι στόχος, αλλά δείκτης, και διαφορετικές ενότητες μπορεί να έχουν διαφορετικά επίπεδα στόχου.
Το Line Coverage δείχνει πόσες γραμμές κώδικα εκτελέστηκαν. Το Branch Coverage — πόσοι κλάδοι (if-else, switch) ελέγχθηκαν. Μια γραμμή με if μπορεί να εκτελεστεί, αλλά ο true κλάδος να ελεγχθεί και ο false — όχι. Το Branch Coverage είναι πιο αυστηρό και εντοπίζει περισσότερα παραλειφθέντα σενάρια.
Στο CI/CD, η κάλυψη ενσωματώνεται μέσω Quality Gate: το build μπλοκάρεται αν η κάλυψη είναι κάτω από το όριο. Για Android χρησιμοποιείται JaCoCo + SonarQube, για iOS — xcodebuild -enableCodeCoverage με ανάλυση .xccovreport. Το GitHub Actions διαθέτει έτοιμες ενέργειες για το Codecov.
Ναι, το JaCoCo υποστηρίζει Jetpack Compose μέσω του τυπικού μηχανισμού κάλυψης JVM. Ωστόσο, ο κώδικας Compose περιέχει πολλές παραγόμενες εκφράσεις lambda που το JaCoCo μπορεί να μην καλύπτει πλήρως. Συνιστάται ο αποκλεισμός του παραγόμενου κώδικα compose από την αναφορά μέσω φίλτρων.
Η ψευδής κάλυψη προκύπτει όταν η δοκιμή εκτελεί κώδικα αλλά δεν ελέγχει το αποτέλεσμα. Λύση: γράψτε ελέγχους assert για κάθε σημαντικό σενάριο, χρησιμοποιήστε mutation testing (Pitest) για τον έλεγχο της ποιότητας των δοκιμών, αναλύστε όχι μόνο το ποσοστό αλλά και ποιοι κλάδοι καλύπτονται.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης