单元测试基础上篇——几大常用框架对比

        本文介绍了android里常用的几种单元测试框架:JUnit、Mockito、PowerMock、Robolectric、Espresso 各自的特点和适用场景。

     JUnit

        JUnit是Java编程语言的单元测试框架。 

        JUnit 只能运行在本地开发环境的 Java 虚拟机上,主要测试方法就是断言,即assertEquals()方法。

        然后,通过实现TestRule接口的方式重写apply()方法去自定义Junit Rule,这样就可以在执行测试方法的前后做一些通用的初始化或释放资源等工作,接着在想要的测试类中使用@Rule注解声明使用JsonChaoRule即可。(注意被@Rule注解的变量必须是final的。最后,我们直接运行对应的单元测试方法或类,如果你想要一键运行项目中所有的单元测试类,直接点击运行Gradle Projects下的app/Tasks/verification/test即可,它会在module下的 build/reports/tests/下生成对应的index.html报告。

        Junit4它的优点是速度快,支持代码覆盖率如jacoco等代码质量的检测工具。缺点就是无法单独对 Android UI,一些类进行操作,与原生Java有一些差异。

     Mockito

        Mock 就是模拟的意思,Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取比较复杂的对象(如 JDBC 中的ResultSet 对象),用一个虚拟的对象(Mock 对象)来创建以便测试的测试方法。

        适用场景是我们不需要某个对象真实执行某个方法的代码,只是需要该对象在调用该方法时按照我们的预期返回特定值,这时就可以使用mock()方法模拟这个对象。

        除此之外,它还有很多 验证方法调用的方式如Mockit.when(调用方法).thenReturn(验证的返回值)、verfiy(模拟对象).验证方法 等等。 这里有一点要补充下:简单的测试会使整体的代码更简洁,更可读、更可维护。如果你不能把测试写的 很简单,那么请在测试时重构你的代码。 最后,对于Mockito来说,它的优点是有各种各样的方式去验证"模仿对象"的互动或验证发生的某些行 为。而它的缺点就是不支持mock匿名类、final类、static方法private方法。

     PowerMock

        PowerMock是一个框架,它以更强大的功能扩展了其他模拟库,例如EasyMock。 PowerMock使用自定义的类加载器和字节码操作来对静态方法,构造函数,最终类和方法,私有方法,静态初始化程序的删除等进行模拟。

        PowerMock具有Mockito不支持的强大功能,但是主要面向具有单元测试专业知识的人员,初级开发人员用可能弊大于利(可能与它必遵守面向对象的原则有关)。开发人员避免使用静态函数,保持好代码规范,尽可能不要使用Powermock写测试case。

      Robolectric

        

        Robolectric是一个框架,可将快速可靠的单元测试引入Android。 测试可以在几秒钟内在您工作站上的JVM中运行。

        前面3种我们说的都是Java相关的单元测试方法,如果想在Java单元测试里面进行Android单元测试,还得使用Robolectric。

        对于 Android 应用开发来说,我们需要调用 Android SDK 的 API,JUnit 和 Mockito 都是针对 Java 平台的测试框架的时候,开发好的应用程序需要打包成 APK 文件并安装到 Android 设备上才能运行测试,效率很低。 Robolectric 框架实现了一套在 Java 虚拟机上能运行的 Android SDK,从而使得 Android 应用程序能够脱离 Android 环境运行测试,提高了测试效率。具体来说,Robolectric提供了一系列类似 ShadowToast.getLatestToast()、ShadowApplication.getInstance()这种方式来获取Android平台对应 的对象。可以看到它的优点就是支持大部分Android平台依赖类的底层引用与模拟。缺点就是在异步测 试的情况下有些问题,这是可以结合Mockito来将异步转为同步即可解决。

      Robolectric优势

        像Mockito这样的模拟框架需要针对android sdk进行模拟工作。 在某些情况下,代码量会增加。 Robolectric可以使用不依赖模拟的Android SDK依赖类。由于Robolectric的测试是在JVM中而不是模拟器或设备中执行的,因此它不需要部署或安装即可快速进行。 因此,适合于在实现后立即编写和执行的case。

        解释一下为什么不依赖androidSDK:Robolectric通过实现一套JVM能运行的Android代码,在unit test运行的时候去截取android相关的代码调用,转到自己实现的代码去执行这个调用。e.g.比如Android里面有个类叫Button,Robolectric则实现了一个叫ShadowButton类。这个类基本上实现了Button的所有公共接口。假设你在unit test里面写到String text = button.getText().toString(),在这个unit test运行时,Robolectric判断你调用了Android的button.getText(),在底层截取这个调用,转到ShadowButton的getText方法来执行。(摘自这

        就是说,运行测试时,Robolectric将这些'shadow objects'注入到实际的Android类中。所以测试在JVM上运行但是无需启动Android实例。

        Robolectric另一个优势是可以处理用c实现的代码,例如view的inflatie 和资源加载,像真机上一样进行测试。也可以为特定的SDK方法提供自己的实现,例如,可以模拟错误条件或现实世界中的传感器的行为。

      Espresso

        Espresso,用于编写Android UI测试用例的自动化测试框架,是开源工具,集成在 Android Studio中。Android官方网站还建议将Espresso与ActivityTestRule一起使用。

espresso优势 参考链接  ——     翻译整理如下:

        开发人员写测试case时需求:1.更改代码后,需要很繁琐地验证每个build 。2.如果测试依赖远程服务器和其他工作站,测试会变慢。3.无论对IDE还是对后续集成,单元测试和功能测试都应该是易于执行的。4.OS升级之后,APP也应该能被测试。5.模拟器和真机要都可以测试。

优势:

1. Espresso工作流程操作简单
允许开发人员将测试套件构建为独立的APK,和被测app一起安装。

2.快速可靠的反馈给开发人员
当开发人员试图加速部署时,Espresso会向他们提供有关代码更改的快速反馈,以便他们可以继续进行下一个功能或缺陷修复。具有健壮且快速的测试框架起着关键作用。Espresso不需要任何服务器(例如Selenium Remote WebDriver)进行通信;相反,它与应用程序并排运行,并向开发人员提供非常快速(几分钟)的测试结果。

3.减少测试碎片
由于Espresso提供了一种同步的执行方法,因此测试周期的稳定性非常高。 Espresso中有一个内置的机制,可以在进行测试的下一步之前验证元素或对象是否实际显示在屏幕上。当遇到“未检测到对象”和其他错误时,可以消除测试执行的中断。

4.易于开发
Espresso自动化测试基于Java和Junit,是Android程序员的核心技能。集成在Android Studio IDE中,不用设置或升级。

      总结

        个人理解,写单元测试首选Mockito。但是怎么避免mockito要依赖android库这个弱项呢,把代码解耦,比如使用MVP,将业务逻辑与View逻辑分开,这样业务逻辑(Presenter)就不会对Android库有任何依赖,就不需要Mock它们)。那么View层往往由Activity / Fragment实现,这时可以使用Robolectric。Robolectric基本上重新实现了Android框架的各个部分,但实现方式有些不同,所以仅在必要时使用(对view层写case)。最后考虑PowerMock,用来模拟静态类(例如Math),或者可以模拟静态Android类。

       下篇会记录Junit、Mockito、Robolectric的单元测试代码的入门写法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值