Robolectric 是一个由 Google 维护的开源框架,它允许您在 JVM 内部的模拟 Android 环境中运行测试,而无需仿真器的开销和不稳定。它支持从 Lollipop(API 级别 21)以来的所有 Android 版本。
许多大型项目使用 Robolectric 来提高测试的速度和可靠性,并减少在真实设备或仿真器上运行测试的相关费用。这包括大多数严重依赖 Robolectric 的 Google 应用。
Robolectric 不能完全替代仿真器,因为它不支持所有功能和 API。例如,Robolectric 没有仿真器那样的屏幕,并且某些 API 仅部分受支持。但是,它模拟了 Android 的足够部分,可以可靠地运行单元测试和大多数 UI 测试。
测试策略
您可以通过 Robolectric 采用两种测试策略:单元测试和 UI 测试。
单元测试
Robolectric 被设计为一种在 Android 应用中启用“单元测试”的方式。例如,您可以模拟 Activity 的启动并测试其中的逻辑,调用所有生命周期方法。
您还可以使用 Robolectric 的模拟对象(称为 shadows)作为单元测试的依赖项。例如,如果您的类使用 Bundle 或您需要模拟 蓝牙 连接。
通常,如果您实现可测试架构,则无需使用 Robolectric 进行单元测试,因为您的代码应可在隔离环境中进行测试,不依赖于 Android 框架。
UI 测试
Robolectric 还可以运行 UI 测试,例如 Espresso 或 Compose 测试。您可以通过将仪器化测试移动到 test
源集并设置 Robolectric 依赖项来将其转换为 Robolectric。
android {
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}
dependencies {
testImplementation("junit:junit:4.13.2")
testImplementation("org.robolectric:robolectric:4.13")
}
test
源集中存在的任何 UI 测试都将通过 Robolectric 运行。
import androidx.test.espresso.Espresso.onView
@RunWith(AndroidJUnit4::class)
class AddContactActivityTest {
@Test
fun inputTextShouldBeRetainedAfterActivityRecreation() {
// GIVEN
val contactName = "Test User"
val scenario = ActivityScenario.launchActivity<AddContactActivity>()
// WHEN
// Enter contact name
onView(withId(R.id.contact_name_text))
.perform(typeText(contactName))
// Destroy and recreate Activity
scenario.recreate()
// THEN
// Check contact name was preserved.
onView(withId(R.id.contact_name_text))
.check(matches(withText(contactName)))
}
}
大多数 UI 测试不与框架交互,您可以在 Robolectric 上运行它们。您可以在 Robolectric 上运行行为测试,因为它所需的保真度已足够。例如,当 Compose 测试验证点击按钮后 UI 是否已更改。
您可以使用 Robolectric 运行其他 UI 测试,例如屏幕截图测试。但是,由于不同设备渲染屏幕的方式略有不同,保真度会较低。
您必须决定 Robolectric 的实现对于每个用例是否足够好,但以下是一些建议
- 将 Robolectric 用于组件、功能或应用测试的独立 UI 行为测试。通常,这些测试检查 UI 的状态管理和行为,并且不与外部依赖项交互。
- 在像素精度不重要时,使用 Robolectric 截取屏幕截图。例如,测试组件对不同字体大小或主题的反应。
注意:Robolectric 可以原生截取屏幕截图,但您需要第三方库才能使用它执行屏幕截图测试。
Robolectric 与设备测试
总之,Robolectric 提供了足够的保真度来运行大多数 UI 测试,但某些情况仍需要设备测试,例如与系统 UI 相关(如全面屏或画中画)或依赖于不支持的功能(如 WebView
)的情况。