Android Test - 概览

1. 在 Android 平台上测试应用

测试应用是应用开发过程中不可或缺的一部分。通过持续对应用运行测试,您可以在公开发布应用之前验证其正确性、功能行为和易用性。

测试还会为您提供以下优势:

  • 快速获得故障反馈。
  • 在开发周期中尽早进行故障检测。
  • 更安全的代码重构,让您可以优化代码而不必担心回归。
  • 稳定的开发速度,帮助您最大限度地减轻技术负担。

2. 测试基础知识

用户可以在各个层面与您的应用进行互动,从按某个按钮到将信息下载到他们的设备上。因此,在迭代开发您的应用时,您应测试各种用例和交互。 

# 1.组织整理代码以便测试:

随着应用的扩展,您可能会发现有必要从服务器获取数据、与设备的传感器进行交互、访问本地存储或呈现复杂的界面。应用的多功能性需要全面的测试策略。

 > 迭代创建和测试代码

迭代开发某项功能时,您可以先编写一个新测试,也可以将用例和断言添加到现有单元测试。测试最初会失败,因为该功能尚未实现。

务必考虑随着设计新功能而出现的责任单元。对于每个单元,您需要编写相应的单元测试。您的单元测试应几乎囊括与单元的所有可能的互动,包括标准互动、无效输入以及资源不可用的情况。应尽可能利用 Jetpack 库;当您使用这些经过充分测试的库时,您可以专注于验证您的应用特有的行为。 

图 1

完整的工作流(如图 1 所示)包含一系列嵌套的迭代周期,其中一个由界面驱动的漫长而缓慢的周期用来测试代码单元的集成。您可以使用更短且更快的开发周期来测试单元本身。这一组周期一直持续到您的应用满足每个用例为止。

 > 将应用看作一系列模块

为了使您的代码更易于测试,应从模块的角度进行开发,其中每个模块代表用户在您的应用中完成的一项特定任务。这种开发角度与基于堆栈的应用视图(通常包含代表界面、业务逻辑和数据的层)形成对比。

务必在每个模块周围设置明确定义的界限,并随着应用规模和复杂性的增长而创建新模块。每个模块应只重点关注一个领域,并且用于模块间通信的 API 应保持一致。为更轻松、快捷地测试这些模块间的交互,不妨考虑创建模块的虚假实现。在测试中,一个模块的真实实现可以调用另一个模块的虚假实现。

3. 配置测试环境

设置在应用中创建测试所需的环境和依赖项时,请遵循本部分中所述的最佳做法。

#1. 根据执行环境组织整理测试目录

Android Studio 中的典型项目包含两个用于放置测试的目录。请按以下方式组织整理您的测试:

  • androidTest 目录应包含在真实或虚拟设备上运行的测试。此类测试包括集成测试、端到端测试,以及仅靠 JVM 无法完成应用功能验证的其他测试。
  • test 目录应包含在本地计算机上运行的测试,如单元测试。

#2. 考虑在不同类型的设备上运行测试的利弊

在设备上运行测试时,您可以从以下类型中进行选择:

  • 真实设备: 可提供最高的保真度,但运行测试所花费的时间也最多。
  • 模拟设备(如 Robolectric): 可提供较高的测试速度,但代价是保真度较低。
  • 虚拟设备(如 Android Studio 中的模拟器): 则平衡了保真度和速度。

#3. 考虑是否要使用测试替身

创建测试时,您可以选择创建真实对象或测试替身,如虚假对象或模拟对象。通常,在测试中使用真实对象比使用测试替身要好,尤其是当被测对象满足以下某个条件时:

  • 该对象是数据对象。
  • 除非与依赖项的真实对象版本通信,否则该对象无法运行。事件回调处理程序就是一个很好的例子。
  • 很难复制该对象与依赖项的通信。SQL 数据库处理程序就是一个很好的例子,其中内存中数据库提供的测试比数据库结果的虚假对象更可靠。

4. 编写测试

配置完测试环境后,就该编写用来评估应用功能的测试了。本部分介绍如何编写小型、中型和大型测试。

#1. 测试金字塔的级别

图 2. 测试金字塔

测试金字塔(如图 2 所示)说明了应用应如何包含三类测试:

  • 小型测试是指单元测试,用于验证应用的行为,一次验证一个类。
  • 中型测试是指集成测试,用于验证模块内堆栈级别之间的互动或相关模块之间的互动。
  • 大型测试是指端到端测试,用于验证跨越了应用的多个模块的用户操作流程。

沿着金字塔逐级向上,从小型测试到大型测试,各类测试的保真度逐级提高,但维护和调试工作所需的执行时间和工作量也逐级增加。因此,您编写的单元测试应多于集成测试,集成测试应多于端到端测试。虽然各类测试的比例可能会因应用的用例不同而异,但我们通常建议各类测试所占比例如下:小型测试占 70%,中型测试占 20%,大型测试占 10%

#2. 编写小型测试

您编写的小型测试应该是高度集中的单元测试,能够详尽地验证应用中每个类的功能和约定。

在特定类中添加和更改方法时,请针对它们创建和运行单元测试。如果这些测试依赖于 Android 框架,请使用与设备无关的统一 API,如 androidx.test API。这种一致性可让您在本地运行测试,而无需使用物理设备或模拟器。

如果您的测试依赖于资源,请在 应用的 build.gradle 文件中启用 includeAndroidResources 选项。然后,您的单元测试可以访问编译版本的资源,从而使测试更快速且更准确地运行。

app/build.gradle

    android {
        // ...

        testOptions {
            unitTests {
                includeAndroidResources = true
            }
        }
    }
    

# 本地单元测试

尽可能使用 AndroidX Test API,以便您的单元测试可以在设备或模拟器上运行。对于始终在由 JVM 驱动的开发计算机上运行的测试,您可以使用 Robolectric

Robolectric 会模拟 Android 4.1(API 级别 16)或更高版本的运行时环境,并提供由社区维护的虚假对象(称为“影子”)。通过此功能,您可以测试依赖于框架的代码,而无需使用模拟器或模拟对象。Robolectric 支持 Android 平台的以下几个方面:

  • 组件生命周期
  • 事件循环
  • 所有资源

# 插桩单元测试

您可以在物理设备或模拟器上运行插桩单元测试。不过,这种形式的测试所用的执行时间明显多于本地单元测试,因此,最好只有在必须根据实际设备硬件评估应用的行为时才依靠此方法。

运行插桩测试时,AndroidX Test 会使用以下线程:

  • 主线程,也称为“界面线程”或“Activity 线程”,界面交互和 Activity 生命周期事件发生在此线程上。
  • 插桩线程,大多数测试都在此线程上运行。当您的测试套件开始时,AndroidJUnitTest 类将启动此线程。

如果您需要在主线程上执行某个测试,请使用 @UiThreadTest 注释该测试。

#3. 编写中型测试

除了通过运行小型测试来测试应用的每个单元之外,您还应从模块级别验证应用的行为。为此,请编写中型测试,即用于验证一组单元的协作和交互的集成测试。

您可以根据应用的结构和以下中型测试示例(按范围递增的顺序)来定义表示应用中的单元组的最佳方式:

  1. 视图和视图模型之间的互动,如测试 Fragment 对象、验证布局 XML 或评估 ViewModel 对象的数据绑定逻辑。
  2. 应用的代码库层中的测试,验证不同数据源和数据访问对象 (DAO) 是否按预期进行互动。
  3. 应用的垂直切片,测试特定屏幕上的互动。此类测试目的在于验证应用堆栈的所有各层的互动。
  4. 多 Fragment 测试,评估应用的特定区域。与本列表中提到的其他类型的中型测试不同,这种类型的测试通常需要真实设备,因为被测互动涉及多个界面元素。

如需执行这些测试,请执行以下操作:

  1. 使用 Espresso-Intents 库中的方法。如需简化传入这些测试的信息,请使用虚假对象和打桩。
  2. 结合使用 IntentSubject 和基于 Truth 的断言来验证捕获的 intent。

 # 运行插桩中型测试时使用 Espresso

当您在设备或 Robolectric 上执行类似于下面的界面互动时,Espresso 有助于使任务保持同步:

  • 对 View 对象执行操作。
  • 评估具有无障碍功能需求的用户如何使用您的应用。
  • 找到并激活 RecyclerView 和 AdapterView 对象中的项。
  • 验证传出 intent 的状态。
  • 验证 WebView 对象中 DOM 的结构。

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

#4. 编写大型测试

尽管单独测试应用中的每个类和模块很重要,但验证可引导用户使用多个模块和功能的端到端工作流也同样重要。这些类型的测试会在您的代码中形成不可避免的瓶颈,但您可以通过验证尽可能接近实际成品的应用来最大限度地减轻这种影响。

注意:对于您编写的每个基于工作流的大型测试,您还应编写中型测试来检查工作流中包含的每个模块的功能。这种测试结构可让您更轻松地确定关键用户操作流程的哪一步出现意外行为。

如果您的应用足够小,您可能只需要一套大型测试来评估应用的整体功能。否则,您应按团队所有权、功能垂直领域或用户目标来划分大型测试套件。

通常,最好在模拟设备或基于云的服务(如 Firebase 测试实验室)上而不是在物理设备上测试您的应用,因为这样您可以更方便快捷地测试屏幕尺寸和硬件配置的多种组合。

# Espresso 中的同步支持

除了支持中型插桩测试之外,Espresso 还支持在大型测试中完成以下任务时实现同步:

  • 完成跨应用的进程界限的工作流。仅适用于 Android 8.0(API 级别 26)及更高版本。
  • 跟踪应用中长时间运行的后台操作。
  • 执行设备外测试。

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值