与Android 测试框架相比,Robolectric是否提供任何明显的好处?我已经阅读了有关这两个框架的文档,但据我所知,关于Robolectric的唯一明显好处是它在 JVM 上而不是 DalvikVM 上运行,使其比 Android 框架更快。
还有其他突出的主要好处吗?
与Android 测试框架相比,Robolectric是否提供任何明显的好处?我已经阅读了有关这两个框架的文档,但据我所知,关于Robolectric的唯一明显好处是它在 JVM 上而不是 DalvikVM 上运行,使其比 Android 框架更快。
还有其他突出的主要好处吗?
2015 年 4 月更新:Gradle 构建工具和 Android Studio现在正式支持单元测试并防止 android.jar 抛出 stub (no real implementation) 错误。所以,是的,当存根被适当地模拟时,它可以在 Java VM 上运行测试。这是一个开始,但仍然无法与 Robolectric 的力量相提并论。还有第三种选择,滚动到这个答案的底部。
现在,关于 Robolectric :
优点:这里有几点关于它在单元测试中如何被证明是有用的:
您不需要运行模拟器,因此您可以在不需要模拟器或设备的情况下测试项目的一些非 UI 部分。这也适用于在持续集成/构建服务器上运行测试,不需要启动模拟器实例。
使用 Android Studio,您可以在执行满足测试用例的实现时快速运行一个特定的测试类。您可以在编写代码时进行调试。这是一个巨大的生产力提升。
几乎可以将所有与 android 相关的东西伪装成影子对象,甚至 SQLite。此外,每个影子对象都公开了许多有用的功能,而它们的普通 android 对象不提供这些功能。使用 android Object 的影子对应物,您可以进行内部检查或调用特殊方法。
AsyncTask
在测试sLoopers
等多线程代码时真的很出色Handlers
。您可以暂停和快进线程 Loopers,甚至是主线程。非常适合基于 Handler 的回调测试。
支持 JUnit 4 格式。上次我检查时,Android 仍在使用 JUnit 3。
可以与 Mockito、Espresso 等其他测试工具结合使用。
支持模拟 Activity 实例创建Robolectric.buildActivity()
及其通过ActivityController
. 片段/视图操作也适用于此类模拟活动实例。
现在提供的附加模块包括多 dex、v4 支持、播放服务、地图和 http 客户端。因此,现在使用这些库函数也很容易测试代码。
缺点:我发现它不太好:
Robolectric 擅长协助单元测试,但并未涵盖真实设备或仿真器可以提供的所有功能。例如传感器、gps、open-gl 等。
在进行集成或 UI 测试时,您需要一个模拟器或真实设备,以便活动和服务可以与完整的 android 环境(其他应用程序,例如使用相机应用程序为您的应用程序获取图片)进行交互,而不是受限的。在这里,您需要使用默认测试框架,因为它也具有测试 UI 的功能。
似乎不支持 JNI 加载。因此无法测试具有本机依赖的代码。
截至目前,Robolectric 对谷歌地图 jar 的工作有硬性依赖。并将从 maven 下载另一个 android.jar。因此,项目设置可能需要一些修补。更新:从 v3 开始,它似乎可以毫不费力地通过 Gradle 提取所有依赖项。
较新的 Android 工具支持覆盖率和报告生成等,但仅限于在设备上运行测试时。因此,使用 Robolectric,您必须创建额外的 Gradle 任务(运行 Jacoco)来为您完成。更新:Gradle 2.9 + 附带 jacoco 插件。
由于 gradle 和 android 构建工具都在快速发布更新的构建版本,稳定的 Robolectric 版本有时会在更改的构建工具上出现问题。最典型的问题包括:sdk 版本不兼容、未找到清单、构建输出路径不匹配、资源未加载、构建配置问题等。一些问题也与 android 工具中的错误有关。有时您甚至可能不得不编写自己的自定义测试运行程序或应用变通方法,直到下一个版本修复这些问题。检查未解决的问题并相应地配置测试。
另一种选择是您自己简单地模拟东西,不涉及任何框架。它是“艰难的方式”,但却是最可定制的方式。它带有JMockit的普通 JUnit :
@RunWith(JMockit.class)
public class OtherTest {
public void testHandlerCallback(@Mocked final FragmentTransaction transaction,
@Mocked final FragmentManager manager,
@Mocked final Activity activity,
@Mocked final LayoutInflater inflater,
@Mocked final ViewGroup parent) {
final List<Fragment> fragments = new ArrayList<>();
new Expectations() {{
activity.getFragmentManager(); result = manager;
manager.beginTransaction(); result = transaction;
transaction.add(withCapture(fragments), anyString);
transaction.commit(); result = new Delegate<Void>() {
public int commit() {
View v = fragments.get(0).onCreateView(inflater,parent,null);
Deencapsulation.invoke(v,"onMeasure",0,0);
return 0;
}
};
}};
}
}
上面是一个粗略的内联示例。实际上,您可以创建适当的可重用类(例如FragmentTestHarness
),它将接受测试的组件(例如 a Fragment
)并将其包装在完全隔离的环境中,为测试做好准备。
To share how i do...
Robolectric For SQL, activities flow, for those objects that needed context.
JUnit4 for api's java module to make sure data are return correctly.
Espresso For checking ui display correctly.
When I modified api...I only run jUnit4.
When I modified the data binding between api and UI or Sqlite, then I will only run Robolectric.
When I modified UI I only run Espresso.
Sometimes I will run Robolectric and espresso together, but very rare.
But I will run all before publish to play store.
Because I think there is not real benefit for now. But see how u use it to speed up your product quality and development speed.
Correct me if I am wrong.
只有在需要模拟或伪造Android 框架的情况下(例如,如果您需要上下文),您才会使用Robolectric 。使用Android 测试框架时,您必须为超慢的测试运行仪器化测试。
如果您编写测试以让它们经常运行,例如因为您遵循 tdd 方法,这不是一个选项。所以在这种情况下, Robolectric就派上用场了。
所以Robolectric的主要好处是它比Espresso或一般的仪器测试快得多。
缺点是它伪造了您应该注意的 Android 环境。要验证现实世界的问题,最好使用经典的 Android 框架方法。
最好的方式仍然是以您可以对它进行单元测试并且不需要上下文或任何其他 Android 框架依赖项的方式编写代码。
自 I/O 2018 以来, Robolectric已集成到 Android 测试框架中 - 在官方 Robolectric 页面上查看更多信息并观看I/O 2018中的此视频
Robolectric 的主要优点是速度。使用 Robolectric 进行单元测试不需要正在运行的模拟器或设备来运行测试,因此速度要快得多。
您可能仍然希望有一套针对真实设备运行的集成测试,只是一个小得多的套件。