Robolectric与Androidtesting框架
与Androidtesting框架相比, Robolectric是否提供了明显的优势? 我已经阅读了关于这两个框架的文档,但据我所知 ,关于Robolectric的唯一明确的好处是它运行在JVM而不是DalvikVM上,使得它比Android框架更快。
还有其他什么突出的好处吗?
2015年4月更新 :Gradle构build工具和Android Studio 现在正式支持unit testing,并防止android.jar抛出存根(没有真正的实现)错误。 所以,是的,当适当地模拟存根时,可以在Java虚拟机上运行testing。 这是一个开始,但仍然不能与Robolectric的力量相提并论。 还有第三个select,滚动到这个答案的底部。
现在,关于Robolectric:
优点 :以下是关于如何certificate在unit testing中有用的几点:
-
你不需要运行模拟器,所以你可以testing一些项目的非UI部分,而不需要模拟器或设备。 这也适用于在持续集成/构build服务器上运行testing,不需要启动模拟器实例。
-
使用Android Studio,您可以快速运行一个特定的testing类,以便在执行testing时满足testing用例。 您可以在编写代码时进行debugging。 这是一个巨大的生产力增长。
-
几乎所有与Android相关的东西都可以伪造成影子对象,甚至是SQLite。 再加上每个阴影对象暴露了许多有用的function,这是他们的普通的android对手所不具备的。 与android对象的阴影对应,你可以做内部检查或调用特殊的方法。
-
当testing像
AsyncTask
,Loopers
和Handlers
等multithreading代码时,真的会发光。你可以暂停和快进线程循环,甚至主线程。 非常适合基于Handler的callbacktesting。 -
支持JUnit 4格式。 上次我查了一下,Android仍然支持JUnit 3。
-
可以和Mockito,Espresso等其他testing工具结合使用
-
支持通过
ActivityController
创buildRobolectric.buildActivity()
及其控件的模拟Activity实例。 片段/视图操作也适用于这样的模拟活动实例。 -
现在提供了附加模块 ,其中涵盖了multi-dex,v4-support,play服务,地图和http客户端。 所以,它现在也很容易使用这些库函数来testing代码。
缺点 :我发现它不太好:
-
Robolectric擅长辅助unit testing,但不包括真实设备或仿真器可提供的所有function。 例如传感器,GPS,开放式等等
-
在进行集成或UItesting时,您将需要模拟器或真实设备,以便活动和服务可以与完整的Android环境(其他应用程序,如使用相机应用程序为您的应用程序获取图片)进行交互,而不是有限的。 在这里你需要使用默认的testing框架,因为它也有testingUI的function。
-
JNI加载似乎不被支持。 所以用本地依赖的代码不能被testing。
-
到目前为止,Robolectric对谷歌地图jar的工作有一个硬连线的依赖。 并会从maven下载另一个android.jar。 所以,项目设置可能需要一点修补。 更新:从v3开始,似乎通过Gradle拉动了所有的依赖关系,没有太多的大惊小怪。
-
较新的Android工具支持覆盖和报告生成等,但只有在设备上运行testing时才可以。 所以Robolectric你必须创build额外的Gradle任务(运行Jaococ)来为你做。 更新:Gradle 2.9 +附带jacoco插件。
-
由于Gradle和Android构build工具都以较快速度发布新版本,所以稳定的Robolectric版本有时会在更改后的构build工具中出现问题。 最典型的问题包括:sdk版本不兼容,没有find清单,构build输出path不匹配,资源不加载,构buildconfiguration问题等。一些问题也与android工具中的错误有关。 有时甚至可能需要编写自己的自定义testing运行器或应用解决方法,直到下一个版本修复这些问题。 查看未解决的问题并相应地configurationtesting。
另一个select是简单地模拟自己的东西,没有涉及的框架。 它是“艰难的方式”,但最可定制的方式。 它的纯JUnit与JMockit:
@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; } }; }}; } }
以上是一个简单而直接的例子。 实际上,你可以创build合适的可重用类(比如FragmentTestHarness
),这个类将testing一个组件(比如一个Fragment
),并将其包装在完全隔离的环境中,为testing做好准备。
分享我的工作
Robolectric对于SQL来说,活动stream向那些需要上下文的对象。
JUnit4 for api的java模块确保数据正确返回。
浓缩咖啡用于检查UI显示是否正确。
当我修改API …我只运行jUnit4。
当我修改API和UI或Sqlite之间的数据绑定时,我将只运行Robolectric。
当我修改UI时,我只运行Espresso。
有时我会一起跑Robolectric和浓咖啡,但是很less见。
但是我会在发布之前运行所有的商店。
因为我觉得现在没有真正的好处。 但看看你如何使用它来加快你的产品质量和发展速度。
纠正我,如果我错了。
Robolectric的主要好处是速度。 使用Robolectric进行unit testing不需要运行仿真器或设备来运行testing,因此速度要快得多。
您可能仍然希望拥有一套针对真实设备运行的集成testing,只是一个小得多的套件。