测试基础
用户与 App 有很多不同水平的交互,从点击一个提交按钮到向设备上下载信息。因此,你应该在你迭代开发你的App 时测试各种各样的使用场景和交互。
使用迭代开发工作流程
随着你的App的拓展,你应该会发现从服务器获取数据,与设备的传感器交互,访问本地存储,或者渲染复杂的界面都是必要的。因此你的多功能的 App 需要一种全面的测试策略。
当你迭代开发一个功能时,你可以通过编写一个新的测试,或者添加 case 和断言到一个已经存在的测试。首次测试是失败的,因为功能还没开发完成。
当你设计一个新功能时考虑出现的责任单元是很重要的。对于每一个单元,你应该写一个相关的单元测试。你的单元测试应该几乎包括相关单元中几乎所有可能的交互场景,包含标准的交互,无效的输入,和一些资源无效的场景。
图1迭代,测试驱动开发相关联的两个循环
完整的工作流程,向图1中所显示的那样,包含一系列的嵌套迭代循环,其中一个长时间、慢速的UI驱动循环测试代码单元的集成。你可以用更短,更快的开发循环来测试它本身。这些循环将持续到您的应用程序满足每一个用例。
了解测试金字塔
图2. 测试金字塔,展示了三种你应该包含在你的App 测试中的测试种类
图二中所显示的测试金字塔,说明了您的 App 应该包含三种测试:小的,中等的和大的:
小型测试是一种可以和你的生产系统所隔离的测试。他们通常会模拟每个主要的组件并且快速的在你的机器上运行。
中型测试是位于小型测试和大型测试中间的集成测试。他们集成了一些组件,运行在模拟器或者真实的设备上。
大型测试是通过完成一个 UI 工作流程来运行的集成和UI测试。他们确保关键的最终的用户任务在模拟器或实际设备上按预期工作。
尽管小型测试速度很快,并且重点突出,可以让你快速的定位错误,但是他们也是低保真和独立的,让你很难有信心仅仅通过这些测试就允许您的App工作。当编写大型测试时会遇到一些相反的折衷。
由于不同测试种类特征的不同,你应该包含测试金字塔中的每一层级测试。虽然每个类别的测试比例可能会因为您的 App 用例而变化,但是我们通常建议这样拆分这些种类:70%小型测试,20%中型测试,10%大型测试。
要了解更多关于 Android 测试金字塔的信息,请参考来自 Google I/O 2017大会上的 Android测试驱动开发 系列视频。
编写小型测试
当你添加或者修改应用程序的功能时,请确保这些功能按照预期的方式运行,并针对他们创建和运行单元测试。虽然可以在设备或者模拟器上运行测试,但是在你的开发环境上测试这些单元是更快更容易的。根据需要来添加stubbed 或者 mocked 方法来与 Android 系统交互。
Robolectric
如果您的应用测试环境需要单元测试更广泛的与 Android 框架来交互,你可以用robolectric。这个工具可以很友好的执行。基于 Java 逻辑的 Stubs 模拟 Android 框架。Android团队在维护这个 stubs。
Robolectric 测试效果几乎与在 Android 设备上测试一样,同时比在 Android 设备上测试更快。它也支持 Android 平台的以下几个方面:
Android 4.1(API 16)以上
Android Gradle 2.4版本以上
组件生命周期
事件循环
所有的资源
备注: Robolectric 有属于它自己的一些 API 并且介绍了一些新概念。有关将 Robolectric 的 API 与应用测试集成的更多信息,请看 Robolectric使用指南
Mock对象
你可以通过对 android.jar 的修改版本运行单元测试来监视与您的应用程式进行交互的 Android 框架的元素。这个 JAR 文件不包含任何代码,因此你的 App 对Android 框架调用时默认会抛出异常。为了测试你代码中与 Android 系统交互的每一个元素,你应该使用一个像 Mockito 的框架来配置mock对象。
如果你的代码包含对资源文件的引用或者与 Android 结构有着复杂的交互,你应该使用一种不同的单元测试的方式,例如 Robolectric.
Instrumented单元测试
你也可以在物理设备或者模拟器上运行 Instrumented 单元测试,他不涉及框架的任何模拟或者 stubbing 。然而,因为这种测试方法执行的时间比本地单元测试的执行时间要慢的多,因此你最好只有在评估应用程序对实际设备硬件的行为至关重要时才依赖此方法。
编写中等测试
当你已经在开发环境中测试了应用的每一个单元后,你应该验证这些组件是否在模拟器或设备上也运行良好。中等测试可以允许你完成这部分的开发过程。如果你的 App 的某些组件依赖于物理硬件,那么这些测试尤其重要。
中等测试评估您的 App 如何协调众多的单元,但是他们不测试整个 App 。中等测试的例子包含 Service 测试,集成测试,和模拟外部依赖行为的密封UI测试。
一般来说,在模拟器或者基于云服务 (例如Firebase测试实验室) 上测试你的 App 要比在物理设备上测试好,因为你可以更快更容易的测试很多不同大小的屏幕尺寸和不同的硬件配置的设备。
编写大型测试
尽管独立的测试应用程序中的每个层和功能很重要,但是测试常见的工作流程和包含完整堆栈的使用场景也同等重要,从UI到业务逻辑到数据层。
如果你的 App 足够小,你可能仅仅需要一套大型测试来评估你的 App 的整体功能。否则,你应该根据团队所有权,功能垂直或者用户目标来分割大型测试。
备注: 对于每个你编写的基于工作流程的大型测试,你同时也应该写中型测试来检查工作流程中所包含的每一个 UI 组件的功能。这样的话,你的测试套件可以继续识别关键用户流程中每个步骤中的潜在问题,即使相关的大型测试在前几个步骤中发生错误。
AndroidJUnitRunner 类定义了一个基于 instrumentation 的 JUnit 测试运行器,可以让你在 Android 设备上运行 JUnit3 或者 JUnit4-style 测试类。测试运行器有助于将测试包和被测试的应用程序加载到设备或者仿真器上,运行测试并报告结果.
AndroidJUnitRunner 同时还支持 Android 测试支持库(ATSL)中的以下工具和框架:
JUnit4 Rules
ATSL(Android测试支持库) 包含管理测试中所涉及的关键应用程序组件生命周期的代码,例如 Services 和Activities。要了解如何定义这些规则,请查看 JUnit4 Rules 指南。
Espresso
Espresso 可以执行下列的App内的操作:
对 View 对象执行操作
完成跨越应用程序的工作流程,仅仅在 Android 8.0(API 26) 及以上可用
评估需要访问您的 App 的用户如何使用您的应用
定位并执行 RecyclerView 和 AdapterView 中的 item
验证 intent 的状态
验证 WebView 对象中的 DOM 结构
跟踪 App 内长时间运行的后台操作
想要了解更多关于这些操作和如何在 App 测试中使用它们,请看 Espresso指南
UI Automator
注意: 我们建议仅当您的App必须要和系统进行交互才能完成关键的用例时才使用 UI Automator,由于 UI Automator 与系统因应用和UI进行交互,所以当系统更新时你需要重新运行和修复你的 UI Automator 测试。这些更新包括 Android 平台版本更新和一些 Google Play 服务版本的更新。
作为使用 UI Automator 的替代方案,我们建议添加密封测试或者将你的大型测试分割成一套中小型测试。特别是当测试一个跨进程通信,例如给别的 App 发送信息并且相应 intent 结果。Espresso-Intents 可以帮你编写这些小型测试。
UI Automator框架运行于你的 App 在和系统的 App 进行交互的场景,例如检查当前显示的 UI 的层次结构,截取屏幕截图和分析设备的当前状态。关于 UI Automator 如何观察被测试应用程序的更多详细信息请看 UI Automator指南
Android Test Orchestrator
Android Test Orchestrator 在其自己的Instrumentation 沙箱中运行每一个UI测试,通过减少测试之间的共享状态并且在每个测试基础上隔离应用程序崩溃来提高测试的稳定定。
想要了解更多关于Android Test Orchestrator 在测试您的App时提供的优势,请看 Android Test Orchestrator指南