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 и поддържа както unit тестове, така и инструментални тестове. За 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)
}
Най-честата грешка — надпревара за процент без анализ на качеството на тестовете. Екипът започва да пише тестове заради самите тестове: проверява getter и setter, дублира покритие на различни нива, тества тривиални методи. Това дава висок процент, но не повишава реалното качество.
Високият 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също