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 підтримує фільтрацію класів: можна виключити згенерований код, 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)
}
Найпоширеніша помилка — гонка за відсотком без аналізу якості тестів. Команда починає писати тести заради тестів: перевіряє геттери та сеттери, дублює покриття на різних рівнях, тестує тривіальні методи. Це дає високий відсоток, але не підвищує реальну якість.
Високий 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, блокуючи збірку при падінні mutation score нижче порогу.
Для автоматичного контролю Code Coverage в CI/CD використовуються Quality Gates — порогові значення, при порушенні яких збірка позначається як нестабільна або відхиляється. SonarQube дозволяє налаштувати Quality Gate на основі комбінації метрик: покриття (≥80%), кількість багів, вразливостей та дубльованого коду.
В GitHub Actions Code Coverage інтегрується через action-кроки: запуск тестів з покриттям → завантаження звіту в 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 додатково показує покриття на рівні файлу, класу, методу та рядка, а також історію зміни покриття по спринтах. Це допомагає приймати рішення про рефакторинг та додавання тестів.
Часті запитання
Для мобільних проєктів хорошим вважається покриття 70–80% для бізнес-логіки та 50–60% для UI-компонентів. Вище 80% витрати на тестування починають перевищувати вигоду. Важливо пам'ятати, що відсоток — не ціль, а індикатор, і різні модулі можуть мати різний цільовий рівень.
Line Coverage показує, скільки рядків коду було виконано. Branch Coverage — скільки розгалужень (if-else, switch) було протестовано. Рядок з if може бути виконаний, але true-гілка протестована, а false — ні. Branch Coverage суворіший і виявляє більше пропущених сценаріїв.
В CI/CD покриття інтегрується через шлюз якості (Quality Gate): збірка блокується, якщо покриття нижче порогу. Для Android використовується JaCoCo + SonarQube, для iOS — xcodebuild -enableCodeCoverage з парсингом .xccovreport. GitHub Actions має готові actions для Codecov.
Так, JaCoCo підтримує Jetpack Compose через стандартний механізм покриття JVM. Однак Compose-код містить багато згенерованих lambda-виразів, які JaCoCo може не повністю покривати. Рекомендується виключати згенерований compose-код зі звіту через фільтри.
Хибне покриття виникає, коли тест виконує код, але не перевіряє результат. Рішення: писати assert-перевірки на кожен важливий сценарій, використовувати mutation testing (Pitest) для перевірки якості тестів, аналізувати не лише відсоток, але й які гілки покриті.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також