原文:https://developer.android.com/training/testing/fundamentals.html

用户在不同的级别上与你的应用产生交互。从按下按钮到将信息下载到他们的设备上,因此,你应该在迭代开发应用程序时测试各种用例和交互。

使用迭代开发工作流


当你的应用程序进行扩展时,你可能会发现需要从服务器获取数据,与设备的传感器进行交互,可以还需要访问本地存储,或呈现复杂的用户界面。应用程序的多样性需要一个全面的测试策略。

在迭代开发一个新的特性时,首先需要编写一个新的测试,或者在现有单元测试中添加新的测试例和断言。测试一开始是失败的,因为这个新特性还没有实现。

在设计新功能时,考虑单元测试的设计很重要。对于每个功能单元编写一个相应的单元测试。你的单元测试应该尽可多的涵盖到所有可能与单元的交互,包括标准的交互、无效的输入、以及资源不可用的情况。

图:测试驱动开发:两个周期与迭代过程。

完整的工作流,如上图,包含一系列嵌套的循环迭代。其中长、慢、UI驱动的集成测试,你可以用更短、更快的单元测试驱动开发周期来完成。这一系列循环一直持续到你的应用程序满足每个用例为止。

测试金字塔


图:测试金字塔,显示应该在应用程序的测试套件中包含的三个测试类别。

测试金字塔,如上图所示,说明你的应用程序应该如何包括三种类型的测试:小测试、中测试和大测试。

  • 小测试是你可以在与生产系统隔离的情况下运行的单元测试。它们通常会mock所有主要组件,并在PC上快速运行。

  • 中测试是介于小测试和大测试之间的集成测试。它们集成了几个组件,并在Android模拟器或真实设备上运行。

  • 大测试是通过完成UI工作流来运行的集成和UI测试。它们确保关键的终端用户任务在Android模拟器或真实设备上正常工作。

注:这里测试金字塔的定义是Google针对Android应用的测试划分。不同类型的应用,通过测试金字塔模型进行划层级的划分,以及每层的定义会有所不同。

尽管小测试的速度很快,而且重点突出,可以让您快速处理失败,但它们是低保真和独立的,让你很难相信通过测试的应用是可以正常运行的,所以需要通过大测试进行补足。

由于每个测试类别的不同特性,你的测试工作应该包含测试金字塔的每一层测试。尽管每个类别的测试比例可能因应用程序的使用情况而有所不同,但我们通常建议以下分类:70%的小测试、20%的中等测试和10%的大测试。

小测试


在添加和更改应用程序的功能时,通过创建和编写单元测试来确保这些功能按照预期的来运行。虽然可以在Android模拟器或真实设备中运行单元测试,但是在开发环境中运行单元测试通常会更快、更容易,根据需要添加Stub或mock方法实现与Android系统进行交互。

Robolectric

如果你的应用程序的测试环境要求单元测试与Android框架进行更广泛的交互,那么你可以使用Robolectric。此工具执行测试友好、基于Java 逻辑Stub来模拟Android框架,由社区来维护这些Stub。

Robolectric测试几乎完全符合Android设备上运行测试的完全保真度,但仍比设备测试运行得更快。它还支持Android平台的以下几个方面:

  • Android 4.1(API等级16)及更高版本
  • Android Gradle插件2.4及更高版本
  • 组件生命周期
  • 事件循环
  • 所有资源

Robolectric有自己的一套测试API,并引入了一些新概念。有关将Robolectric的API与应用程序的测试相结合的更多信息,请参见该工具的 用户指南

Mock对象

你可以通过修改Android.jar版本来运行单元测试,从而来监控应用与之交互的Android框架元素。这个JAR文件不包含任何代码,所以你的应用程序调用Android框架默认会抛出异常。 要测试与Android系统交互的代码元素,请使用像Mockito这样的框架来配置模拟对象。

检测单元测试

你也可以在Andorid模拟器或真实设备上运行检测单元测试,而不涉及任何stub或mock框架。因为这种测试形式的执行时间明显比本地单元测试慢,所以最好仅在需要评估应用程序对当前设备硬件的行为时才依赖此方法。

中测试


在开发环境中测试了应用程序的每个单元之后,应验证在模拟器或设备上运行时组件的行为是否正确。 中等测试允许您完成这部分的开发过程。 如果某些应用程序的组件依赖于物理硬件,则这些测试对于创建和运行尤其重要。

中等测试你的应用程序如何协调多个单元,但它们不测试完整的应用程序。中等测试的用例包括服务测试、集成测试以及mock外部依赖性行为的UI测试。

通常情况下,最好在Android模拟器或Firebase测试实验室等基于云服务上测试应用程序,而不是在真实设备上测试应用程序,因为你可以更轻松,快速地测试多种屏幕大小和硬件配置组合。

大测试


尽管测试应用程序中的每一层的功能是非常重要的,但是测试涉及整个堆栈的常见工作流和用例(从UI到业务逻辑到数据层)同样重要。

如果您的应用程序足够小,则可能只需要一套大型测试来评估你的应用程序。 否则,你应该根据团队所有权,垂直功能或用户目标来划分你的大型测试套件。

对于你所编写的每一个大型的基于工作流程的测试,你还应该编写中测试来检查工作流中包含的每个UI组件的功能。通过这种方式,即使在最初的几个步骤中,相应的大型测试也会失败了,你的测试套件仍然可以在关键用户操作的每一步中继续识别潜在的问题。

AndroidJUnitRunner类定义了一个基于JUnit框架的测试运行器,它允许你在Android设备上运行JUnit 3或JUnit 4样式的测试类。便于将测试包和应用程序加载到真实设备或Android模拟器上,运行测试并报告结果。

AndroidJUnitRunner类支持来自Android测试支持库的以下工具和框架:

JUnit4 Rules

测试说明语言包括用于管理的关键应用程序组件的生命周期涉及你的测试代码,如Activitie 和Service。学习如何定义这些规则,看到 JUnit4规则指南

Espresso

Espresso同步异步任务,同时自动执行以下应用内交互:

在View对象上执行操作。 * 完成跨越应用程序进程边界的工作流程。仅在Android 8.0(API级别26)及更高版本上可用。 * 评估具有辅助功能需求的用户如何使用你的应用。 * 查找并激活RecyclerView和AdapterView对象中的项目。 * 验证传出意图的状态。 * 在WebView对象中验证DOM的结构。 * 跟踪你的应用程序中长时间运行的后台操作。

要详细了解这些互动以及如何在应用程序的测试中使用它们,请参阅 Espresso指南

UI Automator

我们建议仅当你的应用程序必须与系统进行交互的操作时,才使用UI Automator来测试你的应用程序。 由于UI Automator与系统应用程序UI交互,因此你需要在每次系统更新后重新运行并修复UI Automator测试。 此类更新包括Android平台版本升级和Google Play服务的新版本。

作为使用UI Automator的替代方案,我们建议添加封闭测试或将大型测试分为一系列小型和中型测试。特别是,一次侧重于测试一个应用程序间通信,例如将信息发送到其他应用程序,并对意图结果进行响应。Espresso-Intents工具可以帮助您编写这些较小的测试。

UI Automator框架在你的应用程序的系统应用程序内执行交互,例如检查当前显示UI的层次结构、截取屏幕截图以及分析设备的当前状态。有关UI Automator如何检查正在测试的应用程序的更多详细信息,请参阅 UI Automator指南

Android Test Orchestrator


Android Test Orchestrator在其自己的Instrumentation沙箱中运行每个UI测试,通过减少测试之间的共享状态并在每个测试的基础上隔离应用程序崩溃来提高测试套件的可靠性。