【摘要】近几年移动互联网行业发展迅猛,带动智能平台飞速发展,致使终端智能产品迅速占据当前的消费市场。本文通过对当前Android系统应用开发模式MVP架构的描述,指出该模式下软件测试的优势与不足,进而提出MVP架构下提高软件产品质量的有效测试方法。即使用mockito+powermock测试框架,完成代码级别的白盒测试方法,来满足提高软件质量的产品需求。
【关键词】MVP架构;白盒測试
随着移动互联网时代的来临,智能手机日益走进人们的生活,改变着大家的生活方式。近几年,智能移动平台发展尤为迅猛,具有代表性的平台包括苹果公司的iOS系统,Google企业的Android系统,加拿大BlackBerry公司的黑莓系统,以及昙花一现的WinPhone系统等等。截止2018年第一季度统计数据,根据最新的凯度移动通信消费者指数(KantarWorldpanelComTech)的智能手机操作系统数据显示,当前Android系统在智能平台系统中的用户占据比重具有绝对地位,高达80%左右,特别是在中国,这个占比率更高达90%。如此庞大的用户量,致使Android应用软件数量增长迅速,但由于Android系统从发布之初,就以开源架构为宗旨,完全开放所有代码及其结构,导致Android系统产品碎片化问题严重,并且由于Android系统相较于传统PC端产品,具有:内存有限,与用户交互频繁,系统软件碎片化,用户群分散等诸多特点,这些不同都给软件测试任务带来前所未有的挑战,那么如何才能更高效地实施测试,提高产品质量,就成为解决问题的核心。
一、MVP架构介绍
MVP是Model-View-Presenter的首字母缩写,分别表示模型层-视图层-发布层,它是MVC架构的一种演变。相较于MVC架构的缺点,MVP架构降低了视图对模型的依赖与交互,基于MVP架构开发,使用户界面与业务逻辑分离,架构更灵活,能有效提高程序开发的效率。Model层负责数据的检索以及数据持久化等操作;View层负责UI界面的显示和用户交互操作;Presenter层作为Model与View之间的桥梁,负责两者之间的业务逻辑处理。逻辑结构如图1所示。
MVP模式可以更好地将APP程序代码分层,进而为单元测试提供更好的实践结构。
二、移动端单元测试框架比较
单元测试以详细设计说明书和源程序清单为依据,常采用白盒测试用例为主要手段,并组合黑盒测试用例,来寻找模块内部可能存在的常规错误以及逻辑错误。单元测试面向的测试对象是代码,其测试粒度尽可能包含了每一个最小的完整的功能点,并且与边界、接口等测试手段结合,如此细致的测试粒度,就可以很好地保证测试覆盖率,更好地提高产品质量。
(一)Junit+Instrumentition测试框架
junit测试框架是一款成熟产品,因为其运行于jvm上,所以其只能测试纯Java程序,因此,对于Android程序的单元测试来说,Junit具有其局限性。instrumentation是针对Android系统的JUnit扩展,也就是说对于不涉及Android组件的项目,可直接通过JUnit进行单元测试,而对于调用了Android组件的项目可通过Instrumentation进行单元测试。Instrumentation是Android系统自带的测试模块,提供了测试Android四大组件的单元测试接口,但是由于Instrumentation偏底层,封装性较差,并且需要被测试APP的源码,这就给测试实现带来很多代价,因此,直接用Instrumentation而不二次封装的测试手段已经很少被使用。
(二)Robolectric测试框架
Robolectric测试框架是近几年流行的一款封装性较好的单元测试工具。其设计思路是:通过实现Android启动的相关库,完成直接运行在JVM上面的Android代码的设计思想,从而实现尽可能脱离Android运行环境的编译环境,进而高效地降低Android代码及测试用例运行速度的设计核心。
Robolecric是TDD模式在Android系统上的具体实现,该框架具有高效的运行速度,并且在测试服务器请求时,对日常的数据模拟和延时发送模拟,给多线程状态下的测试提供了很好的解决方法。随着日益丰富的测试需求,该框架的缺点日益突出,其缺点主要集中在无法很好地支持异步测试,需要结合其他的框架来配合完成更多功能。并且受mockito框架的限制,对于final,private,static等类型的mock限制,该框架也具有很大的局限性。
(三)Powermock+mockito测试框架
powermock是一个扩展了其他mock框架的、功能更加强大的框架。Powermockito使用一个自定义类加载类和字节码操作来模拟静态方法,构造函数,final类和方法,私有方法,去除静态初始化器等。通过使用自定义的类加载器,简化采用的IDE或者持续集成服务器不需要做任何改变,并且该框架很容易使用。Powermock的设计宗旨是:用少量的方法和注解扩展现有的API来实现额外的功能。
简单实现原理如下:
(1)当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新的loader实例,然后加载该测试用例使用到的类(系统类除外)。
(2)PM会根据mock需求,去修改写在注解@PrepareForTest里面的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。
(3)如果需要mock的是系统类的final方法和静态方法,PM不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求。
三、测试方法实践
使用MVP架构创建Android应用程序的基本步骤包括:
View:是显示数据(Model)并且将用户指令(events)传送到Presenter以便作用于那些数据的一个接口。View通常含有Presenter的引用。在Android开发中通常将Activity或者Fragment作为View层。
Model:对于Model层也是数据层。它区别与MVC架构中的Model,在这里不仅仅只是数据模型。在MVP架构中Model负责对数据的存取操作,例如对数据库的读写,网络的数据的请求等。
Presenter:对于Presenter层它是连接View层与Model层的桥梁并对业务逻辑进行处理。在MVP架构中Model与View无法直接进行交互。所以在Presenter层它会从Model层获取所需要的数据,进行一些适当的处理后交由View层进行显示。这样通告Presenter将View与Model进行隔离,使得View和Model之间不存在耦合,同时也将业务逻辑从View中抽离。
从上述相关描述中,可以看出MVP架构存在如下优点及其缺点。
优点:
(1)增强了Activity中代码的简洁度,保证了Activity仅仅处理生命周期的任务。
(2)分离视图逻辑和业务逻辑,分别将其存储抽象到IView和IPresenter接口中,进而使代码具有更好的可读性,并且更容易维护,降低维护成本。
(3)更易于进行单元测试。由于Android系统的Context问题,致使Android的单元测试很难执行,但是采用MVP架构的系统,完美地解决了这个问题,它可以更好地打桩,更加容易mock。
(4)避免Activity的内存泄漏。由于手机系统相较于PC端来说,内存资源非常有限,那么相对来说,APP更容易发生OOM的问题,而其中最常见的问题就是由于Activity泄漏造成的APPcrash的重大bug。那么如果可以很好地避免该bug的发生,就可以更好地增强用户体验。采用MVP模式,只要在当前Activity的onDestroy里,分离异步任务对Activity的引用,就能避免ActivityLeak。
缺点:
(1)从MVP的架构的分层结构中可以发现,对视图的渲染放在了Presenter中,那么会造成视图与Presenter之间交互频繁,并且Presenter会随着视图的变更而变更。如果Presenter过多地渲染了视图,势必会大大增加Presenter与特定视图间的耦合度。
(2)相较来说,MVP架构会在代码实现中增加代码数量,特别是小项目,代码量增多是一个表面看起来很冗余的问题,但是如果是可复用性非常好的大型项目,MVP架构的优势是非常明显的,会给项目的重构,复用,以及代码安全等各个重要方面带来非常显著的优势。虽然会对架构设计者提出更高的要求,但是,对于实践中项目的联调以及产品进度的把握都有很多的益处。
四、代码片段
(一)实现步骤介绍
(1)创建IPresenter接口,把所有业务逻辑的接口都放在这里,并创建它的实现PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多重实现所有也方便写单元测试)。
(2)创建IView接口,把所有的视图逻辑的接口都放在这里,其实现类是当前的Activity/Fragment。
(3)有图中可以看出,Activity里包含了一个IPresenter,而PresenterCompl里又包含了一个IView并且依赖了Model。Activity里只保留对IPresenter的调用,其它工作全部留到PresenterCompl中实现。
(4)Model并不是必须有的,但一定会有View和Presenter。
(二)实例分析
五、结语
软件测试行为是产品高质量的保障行为之一,而高覆盖率的单元测试方法又是增强产品健壮性的有效技术,只有使用有效的测试手段,才能尽可能地降低产品风险,提高产品质量,减少产品质量问题带来的代价消耗。
综上所述,引入MVP模式使得应用程序的整体架构、代码结构更加清晰,易于理解和组织。由于将业务逻辑与视图逻辑的代码拆分,并分别进行单元测试,整体提高了可测试性,并增强代码健壮性。虽然相比较于MVC模式,MVP架构引入接口带来了一定的代码量,但是MVP架构为Android应用程序提供更清晰的层次结构,更加有效地降低视图与业务之间的耦合度等优点,都是追求高质量代码的核心需求。
参考文献
[1]李灿彬,甘宏.基于MVP架构跨平台的移动应用与开发[J].科技广场,2017(05):45~48.
[2]王念桥.应用MVP模式改进软件架构[J].计算机时代,2012(04):37~38,40
[3]刘升贵.基于MVP模式的Android应用程序实现及其单元测试研究[J].福建电脑,2017(07):94~95.
[4]于浩.Android平台JNI代码单元测试方法研究[D].成都:西南交通大学,2015.
[5]苑树庆.基于Android平台的自动化测试工具的设计与实现[D].沈阳:东北大学,2014.
[6]陈丽萍,张勇,丁智敏.自动化单元测试框架EasyMock分析及其应用[J].巢湖学院学报,2014(06):34~38.
[7]TAMMO,FREESE.EasyMock:DynamicMockObjectsfor Junit[A].Italy,2002:1~5.
[8]JAFADEESHNANDIGAM,TAOYONGLEI.Usingmock objectframeworkstoteachobject-orienteddesign principles[J].2010(01):40~48.
作者簡介:刘萍萍(1982.11—),女,黑龙江哈尔滨人,硕士,研究方向:计算机科学与技术、软件测试。