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)
}
رایجترین اشتباه — دویدن به دنبال درصد بدون تحلیل کیفیت تستها. تیم شروع به نوشتن تست برای تست میکند: 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--). هرچه تعداد بیشتری از انواع جهش توسط تستها کشته شوند، مجموعه تست قابل اعتمادتر است.
نمره جهش هدف — 80% و بالاتر. این بدان معناست که 80% خطاهای مصنوعی توسط تستها شناسایی شدهاند. پوشش کد (Code Coverage) 90% تضمین نمیکند که تستها خطاها را پیدا میکنند — mutation testing ارزیابی عینیتری ارائه میدهد. Pitest میتواند به عنوان Quality Gate در CI ادغام شود و در صورت کاهش نمره جهش زیر آستانه، ساخت را مسدود کند.
برای کنترل خودکار Code Coverage در CI/CD از Quality Gates — مقادیر آستانهای استفاده میشود که در صورت نقض، ساخت به عنوان ناپایدار علامتگذاری یا رد میشود. SonarQube امکان پیکربندی Quality Gate را بر اساس ترکیبی از معیارها فراهم میکند: پوشش (≥80%)، تعداد باگها، آسیبپذیریها و کد تکراری.
در GitHub Actions، Code Coverage از طریق مراحل action ادغام میشود: اجرای تستها با پوشش → بارگذاری گزارش در Codecov → بررسی آستانه. Codecov به طور خودکار PR را با diff پوشش نظر میدهد و نشان میدهد کدام خطوط تغییر کردهاند و چگونه بر درصد کلی تأثیر گذاشتهاند. اگر پوشش کاهش یافته باشد — 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 actionهای آماده برای Codecov دارد.
بله، JaCoCo از Jetpack Compose از طریق مکانیزم استاندارد پوشش JVM پشتیبانی میکند. با این حال، کد Compose حاوی عبارات lambda تولید شده زیادی است که JaCoCo ممکن است به طور کامل پوشش ندهد. توصیه میشود کد compose تولید شده را از طریق فیلترها از گزارش حذف کنید.
پوشش کاذب زمانی رخ میدهد که تست کد را اجرا میکند اما نتیجه را بررسی نمیکند. راهحل: نوشتن بررسیهای assert برای هر سناریوی مهم، استفاده از mutation testing (Pitest) برای بررسی کیفیت تستها، تحلیل نه تنها درصد بلکه اینکه کدام شاخهها پوشش داده شدهاند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید