تست رگرسیون فرآیند بررسی مجدد برنامه پس از اعمال تغییرات برای کشف نقصها در عملکرد قبلاً کارکرده است. هر تغییر کد — قابلیت جدید، رفع باگ یا بازسازی — میتواند ناخواسته قابلیتهای موجود برنامه را از کار بیندازد. تستهای رگرسیون تأیید اینکه عملکرد قدیمی همچنان کارآمد باقی مانده است را خودکار میکنند. طبق تحقیق IBM، 2023، تست رگرسیون بین ۳۰ تا ۷۰٪ از تمام تستهای اجرا شده در تیمهای محصول تجاری را پوشش میدهد که نقش آن را به عنوان سد اصلی در برابر حوادث تولیدی برجسته میکند.
نکات اصلی
تست رگرسیون نوعی تست است که هدف آن تأیید عدم تأثیر تغییرات کد بر عملکرد موجود است. اصطلاح «rگرسیون» به معنای بازگشت به حالت بدتر است — زمانی که عملکردی در نسخه قبلی کار میکرد در نسخه جدید از کار میافتد. تستهای رگرسیون در هر چرخه توسعه به طور مکرر اجرا میشوند که آنها را از تستهای قابلیت جدید که یک بار نوشته میشوند متمایز میکند.
نیاز به تست رگرسیون از اثر تغییرات آبشاری ناشی میشود: رفع باگ در یک ماژول ممکن است مشکل را حل کند اما عملکرد مجاور که به آن وابسته بود را از کار بیندازد. به عنوان مثال، تغییر یک کوئری SQL در مخزن کاربران ممکن است ورود را سریعتر کند اما خروجی دادهای که از همان کوئری استفاده میکرد را خراب کند. تست رگرسیون روی خروجی داده این نقص را قبل از انتشار کشف میکند.
طبق گزارش CISQ 2023، هزینه رفع نقص رگرسیون کشف شده در محیط تولید ۱۵ برابر بیشتر از مرحله اجرای خودکار رگرسیون است. شرکتهایی که در تست رگرسیون خودکار سرمایهگذاری میکنند، بر اساس Capgemini World Quality Report، سهم نقصهای رگرسیون در انتشارات را از ۲۵٪ به ۵٪ در طول یک سال پس از پیادهسازی کاهش میدهند.
چندین رویکرد برای تست رگرسیون وجود دارد که از نظر حجم و معیارهای انتخاب تست متفاوت هستند. انتخاب رویکرد به اندازه پروژه، فراوانی تغییرات و زمان موجود در خط لوله CI بستگی دارد. در زیر انواع اصلی تست رگرسیون با ویژگیهای آنها آورده شده است.
اجرای کامل رگرسیون تمام تستهای خودکار پروژه را بدون استثنا انجام میدهد. این رویکرد حداکثر اطمینان را میدهد اما به منابع محاسباتی و زمان قابل توجهی نیاز دارد. اجرای کامل قبل از انتشارات بزرگ — هر ۲–۴ هفته یک بار — انجام میشود. برای برنامهای با ۵۰۰۰ تست، اجرای کامل بسته به زیرساخت ۲ تا ۶ ساعت طول میکشد.
رویکرد انتخابی فقط تستهای مرتبط با ماژولهای تغییر یافته را اجرا میکند. برای تعیین ارتباط از تحلیل وابستگی در سطح کد استفاده میشود: اگر کلاس UserRepository تغییر کرده باشد، تستهایی که مستقیم یا غیرمستقیم به UserRepository وابسته هستند اجرا میشوند. ابزارهای Jacoco، Android Test Coverage و Xcode Code Coverage نقشههای پوشش را برای انتخاب دقیق ارائه میدهند. اجرای انتخابی در هر pull request انجام میشود و ۵–۱۵ دقیقه طول میکشد.
رگرسیون مبتنی بر ریسک تستها را بر اساس بحرانی بودن عملکرد و احتمال خرابی رتبهبندی میکند. عملکردهای بحرانی — پرداخت، احراز هویت، همگامسازی — در هر تغییر کد تست میشوند. عملکردهای کمکی — صفحه «درباره برنامه»، انیمیشنها — فقط قبل از انتشار تست میشوند. رتبهبندی هر سه ماه یک بار بر اساس دادههای حوادث تولیدی بازبینی میشود.
اغلب مفاهیم تست رگرسیون و ریتست با هم اشتباه گرفته میشوند، اگرچه فرآیندهای متفاوتی هستند. ریتست اجرای مجدد یک تست خاص است که قبلاً ناموفق بوده، پس از رفع نقص. هدف ریتست اطمینان از کارکرد رفع است: باگ دیگر تکرار نمیشود. ریتست یک بار و بلافاصله پس از رفع و تأیید رفع توسط توسعهدهنده انجام میشود.
تست رگرسیون اجرای تستها روی عملکرد موجود است که تغییر نکرده است. هدف اطمینان از این است که رفع یک نقص، نقص جدیدی در جای دیگر ایجاد نکرده است. تستهای رگرسیون در هر چرخه توسعه به طور مکرر اجرا میشوند، صرف نظر از اینکه چه باگهای خاصی رفع شدهاند. تفاوت اصلی: ریتست خود رفع را بررسی میکند، رگرسیون عواقب رفع را بررسی میکند.
در خط لوله CI/CD هر دو فرآیند به صورت ترتیبی انجام میشوند. پس از ادغام pull request، ریتست باگ خاص و سپس اجرای کامل یا انتخابی رگرسیون راهاندازی میشود. طبق SmartBear (2022)، جداسازی این فرآیندها زمان تشخیص اجراهای ناموفق CI را ۳۰٪ کاهش میدهد، زیرا تیم بلافاصله میبیند کدام بخش از نقصها مربوط به رگرسیون و کدام مربوط به رفعهای ناکارآمد است.
خودکارسازی تست رگرسیون یک عامل حیاتی موفقیت برای پروژههای مدرن موبایل است. تست رگرسیون دستی مقیاسپذیر نیست: با مجموعه ۲۰۰ تستی برای یک اجرا ۲–۳ روز کاری مهندس QA نیاز است که اجراهای روزانه را غیرممکن میکند. تستهای رگرسیون خودکار در ۱۰–۶۰ دقیقه بدون دخالت انسان اجرا میشوند که امکان راهاندازی آنها در هر commit یا pull request را فراهم میکند.
برای نگهداری مجموعه رگرسیون در وضعیت بهروز از تحلیل تست استفاده میشود: ابزارهایی مانند Allure، ReportPortal و Xray درصد عبور، مدت زمان و پایداری هر تست را پیگیری میکنند. تستهایی که پایداری آنها زیر ۹۰٪ میرود (اغلب به دلیل تغییرات در الزامات خراب میشوند) به عنوان legacy علامتگذاری و برای بازبینی به مالک ارجاع داده میشوند.
پیکربندی تست رگرسیون خودکار در Android با استفاده از کتابخانه JUnit 5 و Espresso را بررسی میکنیم. مثال رگرسیون انتخابی را نشان میدهد — تست بررسی میکند که پس از بازسازی مخزن کاربران، صفحه پروفایل خراب نشده است. برای iOS از XCTest با منطق مشابه استفاده میشود — تست تکراری روی سناریوی کلیدی.
تست از MockWebServer برای شبیهسازی سرور استفاده میکند و مسیر کامل را بررسی میکند: بارگیری دادههای کاربر، نمایش در صفحه پروفایل و مدیریت خطا در صورت عدم دسترسی به سرور. چنین تستهایی در مجموعه رگرسیون گنجانده شده و در هر تغییر در module-profile اجرا میشوند.
@RunWith(AndroidJUnit4::class)
class ProfileRegressionTest {
@get:Rule
val composeRule = createComposeRule()
@Test
fun profileScreen_rendersCorrectly() {
val user = User(id = 1, name = "Alice", email = "alice@test.com")
composeRule.setContent {
ProfileScreen(user)
}
composeRule.onNodeWithText("Alice").assertIsDisplayed()
composeRule.onNodeWithText("alice@test.com").assertIsDisplayed()
}
@Test
fun profileScreen_handlesNetworkError() {
setNetworkError()
composeRule.onNodeWithText("خطای بارگیری").assertIsDisplayed()
}
}
برای iOS، تست رگرسیون از XCTestExpectation برای بررسی ناهمگام بهروزرسانی UI پس از دریافت داده از API استفاده میکند. تست پاسخ شبکه را شبیهسازی میکند و بررسی میکند که عناصر UI به درستی بهروز شدهاند.
class ProfileRegressionTests: XCTestCase {
func testProfileScreen_rendersCorrectly() {
let viewModel = ProfileViewModel(userId: 1)
let view = ProfileView(viewModel: viewModel)
viewModel.loadProfile()
let expectation = expectation(description: "profile loaded")
viewModel.onProfileLoaded = {
XCTAssertEqual(viewModel.userName, "Alice")
XCTAssertEqual(viewModel.userEmail, "alice@test.com")
expectation.fulfill()
}
waitForExpectations(timeout: 3.0)
}
}
ساخت مجموعه رگرسیون مؤثر یک فرآیند تکراری مبتنی بر دادههای مربوط به نقصها و تغییرات کد است. استراتژی اولیه شامل گنجاندن تمام تستهای موجود در مجموعه رگرسیون و اجرای کامل قبل از هر انتشار است. با رشد پایگاه تست (بیش از ۲۰۰۰ تست)، اجرای کامل بسیار طولانی میشود و رویکرد انتخابی مورد نیاز است.
فاز دوم — پیادهسازی ابزارهای تحلیل وابستگی: Jacoco برای Android، Xcode Test Plan برای iOS. این ابزارها نقشه «تست — کلاس — متد» را میسازند و امکان تعیین اینکه کدام تستها تحت تأثیر یک تغییر خاص قرار گرفتهاند را فراهم میکنند. اجرای انتخابی مبتنی بر تحلیل پوشش، زمان اجرا را ۶۰–۸۰٪ با حفظ ۹۵٪ اثربخشی کشف رگرسیون، طبق Spotify Engineering (2022)، کاهش میدهد.
فاز سوم — نظارت و بهینهسازی مستمر. تستهایی که ۶ ماه ناموفق نبودهاند به مجموعه کماولویت منتقل میشوند. تستهایی که بیش از یک بار در ماه ناموفق هستند کاندیدای بازبینی هستند: یا مشکلات واقعی را میگیرند (نیاز به رفع دارند)، یا بسیار شکننده هستند (نیاز به پایدارسازی دارند). بازبینی سهماهه مجموعه رگرسیون یک رویه استاندارد برای حفظ اثربخشی و سرعت اجرای آن است.
سؤالات متداول
اجرای انتخابی رگرسیون — در هر pull request. اجرای کامل رگرسیون — قبل از هر انتشار و به صورت هفتگی (nightly build). قاعده کلیدی: هرچه اجرا مکررتر باشد، رگرسیونها سریعتر کشف میشوند و هزینه رفع آنها کمتر است. برای پروژههای حیاتی، رگرسیون کامل در هر ادغام امکانپذیر است.
تمام تستهای واحد (رگرسیون پایه)، تستهای یکپارچهسازی روی مؤلفههای کلیدی و تستهای UI روی سناریوهای حیاتی کاربر. شامل نکنید تستهای عملکرد آزمایشی، تستهایی با ناپایداری بالای ۱۰٪ و تستهایی که نیاز به محیط دستی دارند.
تستهای عملکرد حذف شده را پاک کنید، تستها را هنگام تغییر الزامات بهروز کنید، هر سه ماه یک بار ممیزی مجموعه انجام دهید. تحلیل CI — Allure، ReportPortal — به شناسایی تستهای از دست دادهاهمیت کمک میکند: اگر تستی ۳ ماه تغییر نکرده و ناموفق نبوده، کاندیدای حذف از اجرای روزانه است.
از اجرای موازی تستها روی چند دستگاه استفاده کنید، رگرسیون انتخابی مبتنی بر تحلیل پوشش کد تغییر یافته را پیادهسازی کنید، اسکرینشاتهای بصری را برای صفحات نامرتبط غیرفعال کنید. زمان هدف برای اجرای انتخابی — ۵–۱۰ دقیقه، برای اجرای کامل — حداکثر ۲ ساعت.
خیر، تست رگرسیون شامل بررسیهای دستی نیز میشود: تست اکتشافی پس از انتشار، رگرسیون UX و بررسی دسترسیپذیری پس از تغییر رابط. خودکارسازی ۷۰–۸۰٪ از بررسیهای رگرسیون را پوشش میدهد؛ ۲۰–۳۰٪ باقیمانده تستهای دستی هستند که روی سناریوهایی متمرکزند که نمیتوان یا بسیار گران است خودکار کرد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید