Android 进行单元测试难在哪-序

其实不仅仅只有普通 Android 开发工程师觉得测试 Android 应用很恼火,大牛们也受此困扰已久。例如 Jake Wharton 曾经明确地表示:Android 平台自诞生之初就与应用测试势如水火。Don Felker 和 Kaushik Gopal 也在他们的博文里也提出了相同的观点。当然了,他们还提到 Google 的 IOSched 应用,根本就没有进行过测试,据说 IOSched 还是 Android 开发环境中应用开发的最优集合体呢。IOSched 没有进行测试让我们这些开发者很困扰:1、Google 所谓的“测试是高效地进行 Android 开发中的关键一环”真的不是来唬小孩的吗;2、还是 Google 官方的工程师觉得测试 Android 应用简直就是浪费时间?不管怎样,如果这个世界上最优秀的 Android 开发工程师都觉得在 Android 中进行测试很麻烦,那我们这些小菜鸡玩不好测试也是理所当然的了。

多年以来,Android 开发者们为克服在 Android 中难于进行测试的问题绞尽脑汁。Roboletric 就是这些工程师的智慧结晶,它能让开发者们在 JVM 虚拟机上进行 Android 测试。而最近又有博文开始声讨 Fragment,个中翘楚 Square 就表示:老子再也不用 Fragment 这种垃圾玩意了,我们要把业务逻辑都转换到新开发的 Mortar & Flow (MVP 开发框架)框架里,用纯 Java 对象进行编程,完全不依赖 Android 平台的 API。毫无疑问,这些 Java 对象在标准的 Java 测试工具中进行测试是非常简单的。

我坚信那些和 Square 站在统一战线上的开发团队肯定也在想办法将 UI 从实际的业务逻辑中剥离为纯 Java对象,为提高应用的可测试性不懈努力。换句话说,我觉得我们可以不在 Android 中进行单元测试,也不用实现依赖于 Android SDK 的测试单元。我们应该做的是重构应用,让我们能够为应用中的代码实现纯 Java 的测试单元,无论最终能不能真正地提高 Android 的可测试性和健壮性,我觉得这都值得一试。

我感觉到这个思路会是治本良方,所以我们要做的,就是将下图这样的 Android 的应用架构

变成下图这样:

虽然这个方法可能能从根本上解决问题,但它也有很大的风险,尽管如此,我还是坚持认为这个方法值得一试,因为它能拯救万千挣扎在实现 Android 测试单元的开发者们于水火之中,而且不用强迫他们使用第三方的库,毕竟第三库总会让他们滞后于最新的 Android 系统特性。此外,Kent Beck 认为:可测试性好的代码就是架构优秀的代码,如果他的观点是对的,或许我们还能找到架构应用更好的办法。

在接下来的博文里,我将探索“重构 Android 应用以使它们能轻易地通过标准的 Java 工具进行测试”这个方案的可操作性。

在第一、第二篇博文中,我会侧重阐述在 Android 里进行单元测试为什么会带来如此痛苦的体验。我觉得阻碍 Android 测试方法发展的根本原因就在于:Android 系统本身就难于进行测试。缺乏对 Activity 和 Fragment 的合理注入就是让应用难以测试的根本原因,而且认识到这一点是设计可测试强的应用架构的关键。

在第三篇博文中,我会在细节上探讨一个常见的解耦应用代码和 Android SDK的策略。简单来说,这个策略就是:将所有应用的具体行为交给一个 POJO 对象(Plain Ordinary Java Object)完成,这些 POJO 对象都是 Android 无关的接口的 Android 特定实现。

在第四篇博文中,我会指出实现第二篇博文中提出的策略存在的技术难点,并尝试去挖掘可以解决这些难点的方法。在这些难点中,最大的问题在于内存泄漏和繁复的重用代码。

在最后一篇博文中,我会通过展示我提出的架构为 Android 测试性带来的提高让大家觉得进行这样的技术探索是值得花费时间、精力,并且能获得相应回报的。

时间: 2024-08-20 22:38:50

Android 进行单元测试难在哪-序的相关文章

Android 进行单元测试难在哪-终

原文链接 : WHAT I'VE LEARNED FROM TRYING TO MAKE AN ANDROID APP UNIT TESTABLE 原文作者 : Matthew Dupree 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: Mr.Simple 状态 : 完成 在前面的博文中,我给大家介绍并展示了要怎么使用 Square 大法架构 Android 应用,事实上,Square 开发新的 Android 应用架构本意只是增强应用的可测试性.正

Android 进行单元测试难在哪-part2

原文链接 : Why Android Unit Testing is so hard 原文作者 : Matthew Dupree 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: tiiime 状态 : 完成 在Android 进行单元测试难在哪-part1中,我用干货告诉大家:即使是 Google 大牛写出来的代码也无法进行测试.确切地说,我真正告诉大家的是:根本没办法在 SessionDetailActivity 的 onStop() 方法里进行单元

Android进行单元测试难在哪-part4

原文链接 : HOW TO MAKE OUR ANDROID APPS UNIT TESTABLE (PT. 2) 原文作者 : Matthew Dupree 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: Mr.Simple 状态 : 完成 在上一篇博文中,我给大家介绍了新的应用架构方式 - Square 大法,就像我之前说的,Square 大法是 Square 用于使 Fragment 内的业务逻辑能够进行单元测试的通用方法,我还给大家展示了如何使

Android 进行单元测试难在哪-part3

原文链接 : HOW TO MAKE OUR ANDROID APPS UNIT TESTABLE (PT. 1) 原文作者 : Matthew Dupree 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: tiiime 状态 : 完成 在 Android 应用中进行单元测试很困难,有时候甚至是不可能的.在之前的两篇博文中,我已经向大家解释了在 Android 中进行单元测试如此困难的原因.而上一篇博文我们通过分析得到的结论是:正是 Google 官方

Android 进行单元测试难在哪-part1

原文链接 : Against Android Unit Tests 原文作者 : Matthew Dupree 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: tiiime 状态 : 完成 正如我在序中所说,在 Android 中难于进行测试是众多 Android 开发者的共识.上一篇博文发出后,有许多同行回复了我,并对我的观点表示支持: - Andy Dyer (@dammitandy) April 13, 2015 @philosohacker大大

[Android学习十一]Android开发单元测试

网上关于Android单元测试的文字帖子不胜枚举,看完之后能解决问题是好事,不能解决问题那就是浪费时间和经历.大多数文章来自于这篇文章:http://rexstjohn.com/unit-testing-with-android-studio/       自从投入到Android Studio IDE之后基本上就赖着不走了.这里仅讨论AS(Android Studio)中Android单元测试.           开发一个Android应用单元测试这种程序员的自我修养和基本道德测试是必不可少

android开发 单元测试

1.测试用例类必须得继承AndroidTestCast类2.测试用例类使用public 修饰3.测试用例的测试方法使用public修饰4.测试用例的测试方法的返回值应该是void5.测试用例中测试方法不应该有任何参数6.测试用例中测试方法必须抛出异常 ,在你的方法加上:throws throwable7.测试用例中测试方法名必须以test开头:test+你的方法名, android开发 单元测试,布布扣,bubuko.com

Android之单元测试学习

1.单元测试概念 单元测试(又称为模块测试),检验程序模块(软件设计的最小单位)正确性的测试工作,常常是程序员写的一段代码.对于面向对象编程,最小单元就是方法,包括基类(超类).抽象类.或者派生类(子类)中的方法. android中的测试框架是扩展的junit3,所以在学习android的单元测试之前,可以先学习junit3的使用.junit3要学习的东西其实也不多. junit3的入门可以参考:http://android.blog.51cto.com/268543/49994 文档:http

Android Studio 单元测试

Android Studio单元测试流程 *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: pointe