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 — podesavanje JaCoCo
android {
buildTypes {
debug {
testCoverageEnabled = true
}
}
}
// Kreiranje JaCoCo izvestaja
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. Параметризација омогућава проверу више улазних података без дуплирања кода, што значајно проширује покривеност грана и услова.
// Parametrizovani test u Kotlin sa 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)
}
Најчешћа грешка — трка за процентом без анализе квалитета тестова. Тим почиње да пише тестове ради тестова: проверава gettere и settere, дуплира покривеност на различитим нивоима, тестира тривијалне методе. То даје висок проценат, али не повећава стварни квалитет.
Висок Code Coverage може створити лажни утисак да је апликација добро тестирана. Тест може извршити линију кода, али не проверити исправност резултата. На пример: тест позива метод за израчунавање попуста, али не проверава износ — линија је извршена, покривеност расте, а грешка није пронађена.
Типична грешка — тестирати само “срећни пут” (happy path) и игнорисати граничне случајеве: празне листе, null вредности, максималне бројеве, неисправне формате. Већина грешака настаје управо на границама и изузецима. Branch coverage помаже да се открију пропуштене гране, али не гарантује проверу граничних вредности.
Mutation Testing је метод процене квалитета тестова при којем се у изворни код уносе мутације (вештачке грешке) и проверава да ли ће тестови пасти. Pitest — популарни алат за mutation testing за Java и Kotlin. Ако тестови нису пали на мутацији — значи да не проверавају тај услов.
Pitest ствара мутанте — измењене копије изворног кода, у којима је, на пример, > замењено са >=, true са false, или је уклоњен позив метода. Затим се за сваког мутанта покрећу тестови. Ако тестови прођу — мутант је преживео, значи да тестови не покривају овај сценарио. Ако тестови падну — мутант је убијен, тест је исправан.
// build.gradle — podesavanje 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 се интегрише кроз акционе кораке: покретање тестова са покривеношћу → отпремање извештаја у Codecov → провера прага. Codecov аутоматски коментарише PR са дифом покривености, показујући које линије су промењене и како је то утицало на укупни проценат. Ако је покривеност пала — PR се блокира до писања додатних тестова.
# GitHub Actions — otpremanje pokrivenosti u 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 има готове акције за Codecov.
Да, JaCoCo подржава Jetpack Compose кроз стандардни механизам JVM покривености. Међутим, Compose код садржи много генерисаних ламбда израза које JaCoCo можда неће у потпуности покрити. Препоручује се искључивање генерисаног compose кода из извештаја кроз филтере.
Лажна покривеност настаје када тест извршава код, али не проверава резултат. Решење: писати assert провере за сваки важан сценарио, користити mutation testing (Pitest) за проверу квалитета тестова, анализирати не само проценат већ и које гране су покривене.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође