单元测试基础——框架概览

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

JUnit

JUnit是Java编程语言的单元测试框架。 JUnit在测试驱动开发的开发中非常重要,并且是一整套单元测试框架之一,该框架统称为xUnit,它起源于SUnit。

Junit4的主要测试方法就是断言,即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 测试就是在测试过程中,对于某些不容易构造(如 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,它提供了一套能运行在JVM的Android代码。它提供了一系列类似 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类。

最后一点点题外话

android studio怎么开始写单元测试?

——编写:在要写测试的方法上右键-》 go to -》 test.就可以编写测试用例。

——执行:对应的文件目录上,右键-》Run **test

猜你喜欢

转载自blog.csdn.net/qq_33298609/article/details/121447659