Robolectric 与 Android 测试框架

Posted

技术标签:

【中文标题】Robolectric 与 Android 测试框架【英文标题】:Robolectric vs Android Test Framework 【发布时间】:2013-08-18 18:02:05 【问题描述】:

RobolectricAndroid 测试框架 相比有什么明显的优势吗?我已经阅读了有关这两个框架的文档,但据我所知,关于 Robolectric 的唯一明显好处是它在 JVM 上而不是 DalvikVM 上运行,使其比 android 框架更快。

还有其他突出的主要好处吗?

【问题讨论】:

这是很久以前问的。 android 测试框架是否比 robolectric(截至今天 2017/06)更好? 【参考方案1】:

2015 年 4 月更新:Gradle 构建工具和 Android Studio now officially support unit testing 并防止 android.jar 抛出 stub (no real implementation) 错误。所以,是的,当存根被适当地模拟时,它可以在 Java VM 上运行测试。这是一个开始,但仍然无法与 Robolectric 的力量相提并论。还有第三种选择,滚动到此答案的底部。

现在,关于 Robolectric:

优点:以下是关于它如何在单元测试中被证明有用的几点:

    您不需要运行模拟器,因此您可以在不需要模拟器或设备的情况下测试项目的一些非 UI 部分。这也适用于在持续集成/构建服务器上运行测试,不需要启动模拟器实例。

    使用 Android Studio,您可以在执行满足测试用例的实现时快速运行一个特定的测试类。您可以在编写代码时进行调试。这是一个巨大的生产力提升。

    几乎可以将所有与 android 相关的东西伪装成影子对象,甚至 SQLite。此外,每个影子对象都公开了许多有用的功能,而它们的普通 android 对象不提供这些功能。使用 android Object 的影子对应物,您可以进行内部检查或调用特殊方法。

    在测试AsyncTasks、LoopersHandlers 等多线程代码时真的很出色。您可以暂停和快进线程 Loopers,甚至是主线程。非常适合基于 Handler 的回调测试。

    支持 JUnit 4 格式。我上次检查时,Android 仍在使用 JUnit 3。

    可与 Mockito、Espresso 等其他测试工具结合使用。

    支持模拟 Activity 实例创建Robolectric.buildActivity() 并通过ActivityController 对其进行控制。片段/视图操作也适用于此类模拟活动实例。

    现在提供了add-on modules,涵盖了multi-dex、v4-support、播放服务、地图和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 工具中的错误有关。有时您甚至可能不得不编写自己的自定义测试运行程序或应用变通方法,直到下一个版本修复这些问题。查看open issues 并相应地配置测试。


另一种选择是您自己简单地模拟东西,不涉及任何框架。它是“艰难的方式”,但却是最可定制的方式。它带有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),它将测试组件(例如 Fragment)并将其包装在完全隔离的环境中,为测试做好准备。

【讨论】:

与 Android 测试框架相比,robolectric 有什么缺点吗? 在我们已经得到 Genymotion 的时候,似乎有些部分不是真的? @ThuyTrinh 两者没有比较。 Genymotion 是另一个模拟器(bluestacks、kemu 等也是如此)。它不能解决与 Robolectric 相同的问题。 这是 2 年前的事了。那么android测试框架比robolectric好吗? @Chisko 更新了 Jmockit 链接,因为以前的域名似乎不再与 JMockit 关联。【参考方案2】:

分享我的做法...

机器人电动 对于 SQL,活动会流动,对于那些需要上下文的对象。

JUnit4 用于 api 的 java 模块以确保数据正确返回。

浓缩咖啡 用于检查 ui 显示是否正确。

当我修改 api...我只运行 jUnit4。

当我修改了 api 和 UI 或 Sqlite 之间的数据绑定时,我只会运行 Robolectric。

当我修改 UI 时,我只运行 Espresso。

有时我会同时运行 Robolectric 和 espresso,但很少见。

但我会在发布到游戏商店之前运行所有内容。

因为我认为目前没有真正的好处。但是看看你如何使用它来加快你的产品质量和开发速度。

如果我错了,请纠正我。

【讨论】:

你有一些我可以看的样本吗? :D【参考方案3】:

只有在需要模拟或伪造 Android 框架 的情况下,您才会使用 Robolectric,例如如果您需要上下文。使用 Android 测试框架 时,您必须运行 Instrumented 测试 来处理超慢的测试。

如果您编写测试是为了让它们经常运行,例如因为您遵循 tdd 方法,所以这不是一个选项。所以在这种情况下 Robolectric 就派上用场了。

因此,Robolectric 的主要优点是它比一般的 Espresso仪器测试 快得多。

缺点是它伪造了一个您应该注意的 Android 环境。要验证现实世界的问题,最好使用经典的 Android 框架方法。

最好还是以一种可以对代码进行单元测试并且不需要上下文或任何其他 Android 框架依赖项的方式编写代码

Robolectric 自 2018 年 I/O 以来已集成到 Android 测试框架中 - 请访问 official Robolectric page 了解更多信息并观看 2018 年 I/O 中的 this video

【讨论】:

【参考方案4】:

Robolectric 的主要优点是速度。使用 Robolectric 进行单元测试不需要正在运行的模拟器或设备来运行测试,因此速度要快得多。

您可能仍然希望有一套针对真实设备运行的集成测试,只是一个小得多的套件。

【讨论】:

以上是关于Robolectric 与 Android 测试框架的主要内容,如果未能解决你的问题,请参考以下文章

如何使用robolectric对Android音频录制应用进行单元测试

Android:如何在 Robolectric 中测试 PDFView?

Android单元测试系列-Robolectric

Android单元测试系列-Robolectric

Android robolectric 测试清单合并问题(android 信标库)

配置同时使用PowerMock和Robolectric对Android进行单元测试