Robolectric یک فریمورک برای تست واحد برنامههای Android است که به شما امکان میدهد تستها را مستقیماً روی JVM بدون شبیهساز یا دستگاه فیزیکی اجرا کنید. این فریمورک فراخوانیهای Android SDK را رهگیری میکند و اشیاء shadowای را ارائه میدهد که رفتار کامپوننتهای واقعی را شبیهسازی میکنند. طبق Robolectric Documentation, 2025، اشیاء shadow حدود 15 هزار کلاس Android API را جایگزین میکنند و ایزولهسازی تستها از پلتفرم را تضمین میکنند.
نکات اصلی
Robolectric یک فریمورک متنباز است که در سال 2010 برای تسریع تست برنامههای Android ایجاد شد. به جای اجرا روی شبیهساز یا دستگاه، Robolectric پیادهسازیهای shadowای از کلاسهای Android SDK ارائه میدهد که مستقیماً روی ماشین مجازی Java (JVM) کار میکنند. این امکان اجرای هزاران تست را در ثانیهها فراهم میکند.
تست سنتی Android نیاز به اجرای برنامه روی شبیهساز دارد که 3–10 دقیقه برای ساخت APK، نصب و اجرا زمان میبرد. Robolectric این مرحله را حذف میکند: تستها به عنوان تستهای معمولی Java/Kotlin کامپایل شده و از طریق JUnit اجرا میشوند. این چرخه بازخورد را در چند ثانیه به جای دقیقهها فراهم میکند.
Robolectric از همه نسخههای Android از API 16 (Android 4.1) تا آخرین نسخه پایدار پشتیبانی میکند. برای هر نسخه، مجموعه مربوطی از اشیاء shadow ارائه میشود که رفتار دقیقاً همان نسخه پلتفرمی را که برنامه روی آن تست میشود شبیهسازی میکنند.
معماری Robolectric بر اساس مکانیزم رهگیری فراخوانیها از طریق جایگزینی classloader است. وقتی تست متدی از Android SDK را فراخوانی میکند، Robolectric فراخوانی را رهگیری کرده و به شی shadow هدایت میکند. شی shadow یک کلاس Java است که رفتار واقعی کامپوننت Android را تقلید میکند اما بدون پلتفرم بومی کار میکند.
اشیاء shadow متدهای کلیدی کلاسهای اصلی Android را پیادهسازی میکنند. مثلاً ShadowTextView متدهای getText()، setText()، getCurrentTextColor() و دیگران را شبیهسازی میکند. وقتی textView.setText("Hello") فراخوانی میشود، shadow رشته را ذخیره کرده و هنگام فراخوانی getText() آن را برمیگرداند. این تستها را از رندرینگ واقعی و سرویسهای سیستم جدا میکند.
Robolectric بیش از 200 کلاس shadow را پشتیبانی میکند که کامپوننتهای اصلی Android SDK را پوشش میدهند: Activity، Fragment، TextView، Button، RecyclerView، WebView، LocationManager، ConnectivityManager و بسیاری دیگر. اشیاء shadow از همان سلسلهمراتب ارثبری کلاسهای اصلی Android پیروی میکنند.
نصب Robolectric در پروژه Gradle نیاز به افزودن وابستگی testImplementation "org.robolectric:robolectric:4.x" دارد. همچنین باید پیکربندی android:sdk را در فایل build.gradle مشخص کرده و android:testInstrumentationRunner را اضافه کنید. برای کار با Robolectric پلاگین android-test مورد نیاز نیست.
پس از افزودن وابستگی، باید دایرکتوری را برای manifest، منابع و assets پیکربندی کنید. Robolectric به طور خودکار AndroidManifest.xml را پیدا میکند، اما ممکن است نیاز به مشخص کردن مسیر به صورت دستی از طریق @Config یا ویژگیهای سیستم باشد. برای پروژههای چندماژولی، پیکربندی برای هر ماژول جداگانه تنظیم میشود.
// build.gradle — پیکربندی Robolectric
android {
testOptions {
unitTests.includeAndroidResources = true
unitTests.all {
systemProperty 'robolectric.dependency.dir',
project.rootDir.absolutePath + '/build/intermediates'
}
}
}
dependencies {
testImplementation 'org.robolectric:robolectric:4.13'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}
@Config امکان بازنویسی پارامترهای تست را فراهم میکند: sdk (نسخه API)، manifest (مسیر به manifest)، qualifiers (پیکربندی صفحه، زبان). این برای تست رفتار برنامه در نسخههای مختلف Android، جهتهای صفحه و زبانها مفید است.
تستهای Robolectric به عنوان تستهای واحد معمولی با @RunWith(RobolectricTestRunner.class) برای JUnit 4 یا از طریق RobolectricExtension برای JUnit 5 نوشته میشوند. ActivityController چرخه حیات Activity را مدیریت میکند: create()، start()، resume()، pause()، stop()، destroy(). این امکان تست جزئی هر انتقال حالت را فراهم میکند.
برای تست Activity از ActivityController استفاده میشود که به صورت ترتیبی از مراحل چرخه حیات عبور میکند. دسترسی به Activity از طریق controller.get() انجام میشود. همه کامپوننتهای دید از طریق findViewById مانند برنامه واقعی در دسترس هستند. اشیاء shadow امکان بررسی متنها، قابلیت مشاهده، رنگها و سایر ویژگیهای view را فراهم میکنند.
@RunWith(RobolectricTestRunner.class)
@Config(sdk = BuildConfig.SDK_INT)
public class MainActivityTest {
@Test
public void testActivityDisplaysGreeting() {
ActivityController<MainActivity> controller =
Robolectric.buildActivity(MainActivity.class);
controller.create().start().resume();
MainActivity activity = controller.get();
TextView greeting = activity.findViewById(R.id.greeting);
ShadowTextView shadow = Shadows.shadowOf(greeting);
assertEquals("Welcome!", shadow.getText());
}
}
Robolectric فراخوانیهای startActivity() را رهگیری میکند و امکان بررسی intentهای ارسالشده را از طریق ShadowActivity فراهم میکند. این امکان تست ناوبری را میدهد: بررسی اینکه با کلیک دکمه، Intent با Action، Data و پارامترهای Extra صحیح ارسال میشود.
@Test
public void testNavigationToDetails() {
controller.create().start().resume();
MainActivity activity = controller.get();
activity.findViewById(R.id.detailsButton).performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
Intent intent = shadowActivity.getNextStartedActivity();
assertEquals(
DetailsActivity.class.getName(),
intent.getComponent().getClassName()
);
}
Robolectric و شبیهساز وظایف متفاوتی را حل میکنند. Robolectric برای تستهای واحد سریع، بررسی منطق UI، کامپوننتهای تجاری و مخازن ایدهآل است. شبیهساز برای تستهای ابزاری، بررسی ادغام با API، تست دوربین، سنسورها و عملکرد ضروری است.
| ویژگی | Robolectric | شبیهساز |
|---|---|---|
| سرعت | ~5 ثانیه برای 100 تست | ~5 دقیقه برای 100 تست |
| راهاندازی | بدون ساخت APK | نیاز به ساخت APK |
| API واقعی | شبیهسازی shadow | Android SDK بومی |
| آماده استفاده | فقط JUnit | هر فریمورکی |
Robolectric برای تست ViewModel، Repository و UseCase — کامپوننتهایی که از Android SDK استفاده میکنند اما نیاز به UI واقعی ندارند — عالی است. ViewModel از طریق تست JUnit معمولی با RobolectricExtension تست میشود، در حالی که کامپوننتهای چرخه حیات (LiveData، StateFlow) در محیط shadow بدون mock کار میکنند.
Robolectric از LiveData به صورت آماده پشتیبانی میکند: میتوان در تست روی LiveData مشترک شد، وضعیت را از طریق ViewModel تغییر داد و مقدار تولیدشده را بررسی کرد. برای عملیات ناهمگام از InstantTaskExecutorRule یا runBlocking برای کوروتینها استفاده میشود. این نیاز به mock کردن کامپوننتهای معماری را از بین میبرد.
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [BuildConfig.SDK_INT])
class ProfileViewModelTest {
private val repository = FakeUserRepository()
private val viewModel = ProfileViewModel(repository)
@Test
fun `loading profile sets state to success`() = runBlocking {
viewModel.loadProfile("user123")
val state = viewModel.profileState.getOrAwaitValue()
Assertions.assertTrue(state is UiState.Success)
}
}
اگر اشیاء shadow استاندارد Robolectric کلاس مورد نیاز Android SDK را پوشش نمیدهند، میتوان Shadow سفارشی ایجاد کرد. برای این کار کلاسی با @Implements(ClassName.class) ایجاد شده و متدهای مورد نیاز با @Implementation پیادهسازی میشوند. shadowهای سفارشی از طریق @Config(shadows = [CustomShadow::class]) ثبت میشوند.
Robolectric از تست ContentProvider از طریق Robolectric.buildContentProvider() پشتیبانی میکند. میتوان عملیات CRUD، query با تطبیق URI و مدیریت مجوزهای دسترسی را بررسی کرد. منابع (رشتهها، رنگها، اندازهها) نیز از طریق RuntimeEnvironment.application.resources در دسترس هستند که امکان تست کد وابسته به منابع را فراهم میکند.
انتقال از تستهای ابزاری به Robolectric نیاز به تغییر رویکرد دارد. تستهای ابزاری (AndroidJUnit4) رفتار واقعی را روی شبیهساز بررسی میکنند، Robolectric — منطق ایزولهشده در محیط shadow. توصیه میشود منطق تجاری را با تستهای Robolectric پوشش داده و تستهای ابزاری را برای سناریوهای ادغامی نگه دارید.
در مهاجرت لازم است: AndroidJUnit4 را با RobolectricTestRunner جایگزین کنید، @Config با نسخه SDK هدف اضافه کنید، ActivityTestRule را با ActivityController جایگزین کنید، و وابستگیها را از androidTestImplementation به testImplementation منتقل کنید. Mockها (MockK، Mockito) با Robolectric بدون تغییر کار میکنند — آنها به پلتفرم وابسته نیستند.
Robolectric پشتیبانی نمیکند: تست دوربین (CameraX)، NFC، بلوتوث، بیومتریک، کار با فایلهای واقعی و کتابخانههای بومی. برای این سناریوها تستهای ابزاری روی شبیهساز ضروری هستند. Robolectric همچنین رندرینگ واقعی را بازتولید نمیکند — تستهای layout بهتر است از طریق Compose Test Rule یا Espresso انجام شوند. با این حال برای بررسی منطق تجاری، ناوبری و وضعیتهای ViewModel، Robolectric کاملاً جایگزین شبیهساز با 10 برابر سرعت اجرا میشود.
Robolectric نیاز به JDK 11 یا بالاتر دارد و با AGP (Android Gradle Plugin) از 7.0 تا آخرین نسخه پایدار سازگار است. مدیر SDK Robolectric به طور خودکار نسخههای مورد نیاز Android API را در اولین اجرا دانلود میکند — این یک عملیات یکباره است. برای سرورهای CI توصیه میشود SDK را از قبل از طریق sdkmanager دانلود کنید تا از تأخیر در اولین اجرای تست جلوگیری شود. بهروزرسانی Robolectric به نسخه جدید معمولاً نیازی به تغییر در کد تستها ندارد، فقط بهروزرسانی شماره وابستگی در build.gradle.
Robolectric با فریمورکهای mock محبوب سازگار است: MockK برای Kotlin و Mockito برای Java. Mockها برای ایزولهسازی وابستگیها استفاده میشوند: مخازن، کلاینتهای API، SharedPreferences. قانون اصلی — کلاسهای Android SDK را mock نکنید، برای این کار اشیاء shadow وجود دارند. فقط لایههای برنامه را mock کنید: UseCase، Repository، DataSource و سایر کامپوننتهای منطق تجاری. چنین ترکیبی از اشیاء shadow و mockها حداکثر انعطافپذیری را با حداقل هزینه نوشتن تست فراهم میکند.
سوالات متداول
Espresso یک فریمورک ابزاری است که روی شبیهساز یا دستگاه اجرا میشود. Robolectric یک فریمورک واحد است که روی JVM کار میکند. Espresso رفتار واقعی را تست میکند، Robolectric — منطق ایزولهشده در محیط shadow. آنها مکمل یکدیگر هستند.
بله، Robolectric از Jetpack Compose از نسخه 4.8 پشتیبانی میکند. تستهای کامپوننتهای Compose با ComposeTestRule مانند شبیهساز انجام میشوند. با این حال تستهای Compose روی Robolectric رندرینگ واقعی را بررسی نمیکنند — فقط منطق ترکیب.
Robolectric از پروژههای چندماژولی پشتیبانی میکند. هر ماژول جداگانه با مشخص کردن manifest و منابع خود پیکربندی میشود. برای ماژولهای بدون کامپوننتهای UI، ماژول کتابخانهای بدون پلاگین android کافی است. در پروژههای بزرگ با دهها ماژول، تستهای Robolectric هر ماژول به صورت موازی اجرا میشوند که سرعت بیشتری نسبت به اجرای ترتیبی روی شبیهساز میدهد.
مشکل منابع زمانی رخ میدهد که در build.gradle unitTests.includeAndroidResources = true مشخص نشده باشد یا @Config با مسیر صحیح به manifest وجود نداشته باشد. Robolectric از منابع کامپایلشده از build/intermediates استفاده میکند.
تستهای Robolectric مانند تستهای معمولی Java/Kotlin در Android Studio debug میشوند. breakpoint، step-through debug، بازرسی اشیاء shadow و وضعیت آنها در دسترس است. logging از طریق -Drobolectric.logging=debug در VM options فعال میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید