测试策略

自动化测试可以帮助您以多种方式提高应用质量。例如,它可以帮助您执行验证、捕获回归并验证兼容性。良好的测试策略可以让您利用自动化测试来关注一个重要的优势:**开发人员生产力**。

团队在使用系统化的测试方法并结合基础设施增强时,可以实现更高的生产力水平。这样做可以及时反馈代码的行为。良好的测试策略可以做到以下几点

  • 尽早发现问题。
  • 快速执行。
  • 在需要修复某些内容时提供明确的指示。

此页面将帮助您确定要实现哪种类型的测试、在何处运行以及运行频率。

测试金字塔

您可以根据规模对现代应用中的测试进行分类。小型测试仅关注代码的一小部分,使其快速可靠。大型测试范围广泛,需要更复杂的设置,难以维护。但是,大型测试具有更高的保真度*,并且可以一次发现更多问题。

*保真度是指测试运行时环境与生产环境的相似性。

The distribution of the number of tests by scope is typically visualized in a pyramid.
图 1. 测试数量按范围分布通常以金字塔形式可视化。

大多数应用都应该有许多小型测试和相对较少的大型测试。每个类别中测试的分布应形成一个金字塔,数量较多的小型测试形成底部,数量较少的大型测试形成顶部。

最大程度地降低错误成本

良好的测试策略可在最大程度地提高开发人员生产力的同时,最大程度地降低查找错误的成本

考虑一个可能效率低下的策略示例。在这里,测试数量按规模排列没有形成金字塔。端到端测试过多,组件 UI 测试过少

A top-heavy strategy where a lot of the tests are performed manually and the device tests are only executed nightly.
图 2. 顶部过重的策略,其中许多测试是手动执行的,并且设备测试仅在夜间执行。

这意味着在合并之前运行的测试太少。如果存在错误,测试可能直到夜间或每周的端到端测试运行时才会捕获到它。

务必考虑这对识别和修复错误的成本产生的影响,以及为什么将测试工作重点放在更小、更频繁的测试上的重要性

  • 当单元测试捕获到错误时,通常可以在几分钟内修复它,因此成本很低。
  • 端到端测试可能需要几天时间才能发现相同的错误。这可能会吸引多个团队成员,降低整体生产力并可能延迟发布。此错误的成本更高。

也就是说,效率低下的测试策略总比没有策略好。当错误进入生产环境时,修复程序需要很长时间才能到达用户的设备,有时需要几周时间,因此反馈循环最长且成本最高。

可扩展的测试策略

测试金字塔传统上分为 3 个类别

  • 单元测试
  • 集成测试
  • 端到端测试。

然而,这些概念并没有精确的定义,因此团队可能希望以不同的方式定义其类别,例如使用 5 层

A 5-layer test pyramid with the categories unit tests, component tests, feature tests, application tests, and release candidate tests, in ascending order.
图 3. 5 层测试金字塔。
  • 单元测试在主机上运行,并验证单个功能逻辑单元,不依赖于 Android 框架。
    • 示例:验证数学函数中的越界错误。
  • 组件测试独立于系统中的其他组件,验证模块或组件的功能或外观。与单元测试不同,组件测试的表面积扩展到单个方法和类之上的更高抽象。
  • 特性测试验证两个或多个独立组件或模块的交互。特性测试更大、更复杂,通常在特性级别运行。
  • 应用测试以可部署二进制文件的形式验证整个应用程序的功能。它们是大型集成测试,使用可调试二进制文件(例如包含测试挂钩的开发版本)作为被测系统。
    • 示例:UI 行为测试以验证可折叠设备中的配置更改、本地化和可访问性测试
  • 候选发布版本测试验证发布版本的功。它们类似于应用测试,只是应用二进制文件已缩小和优化。这些是大型端到端集成测试,在尽可能接近生产的环境中运行,而不会将应用公开给公共用户帐户或公共后端。

此分类考虑了保真度、时间、范围和隔离级别。您可以在多个层级上进行不同类型的测试。例如,应用测试层可以包含行为、截图和性能测试。

范围

网络访问

执行

构建类型

生命周期

单元

具有最少依赖项的单个方法或类。

本地

可调试

合并前

组件

模块或组件级别

多个类一起

本地
Robolectric
模拟器

可调试

合并前

特性

特性级别

与其他团队拥有的组件集成

模拟

本地
Robolectric
模拟器
设备

可调试

合并前

应用

应用级别

与其他团队拥有的特性和/或服务集成

模拟
暂存服务器
生产服务器

模拟器
设备

可调试

合并前
合并后

候选发布版本

应用级别

与其他团队拥有的特性和/或服务集成

生产服务器

模拟器
设备

缩小后的发布版本

合并后
发布前

确定测试类别

根据经验法则,您应该考虑金字塔中可以为团队提供正确反馈级别的最低层级。

例如,考虑如何测试此特性的实现:登录流的 UI。根据您需要测试的内容,您将选择不同的类别

被测对象

正在测试内容的描述

测试类别

测试示例类型

表单验证器逻辑

一个根据正则表达式验证电子邮件地址并检查是否输入了密码字段的类。它没有依赖项。

单元测试

本地 JVM 单元测试

登录表单 UI 行为

一个只有在表单验证后才启用的按钮的表单

组件测试

UI 行为测试Robolectric上运行

登录表单 UI 外观

遵循 UX 规范的表单

组件测试

Compose 预览截图测试

与身份验证管理器集成

将凭据发送到身份验证管理器并接收可能包含不同错误的响应的 UI。

特性测试

带有模拟对象的 JVM 测试

登录对话框

按下登录按钮时显示登录表单的屏幕。

应用测试

UI 行为测试Robolectric上运行

关键用户旅程:登录

使用测试帐户针对暂存服务器的完整登录流程

候选发布版本

端到端Compose UI 行为测试 在设备上运行

在某些情况下,某项内容属于哪个类别可能是主观的。可能还有其他原因导致测试上移或下移,例如基础设施成本、不稳定性和测试时间过长。

请注意,测试类别并不决定测试类型,并且并非所有特性都必须在每个类别中进行测试。

手动测试也可以成为测试策略的一部分。通常,质量保证团队执行候选发布版本测试,但他们也可以参与其他阶段。例如,针对没有脚本的特性中的错误进行探索性测试。

测试基础设施

测试策略必须得到基础设施和工具的支持,以帮助开发人员持续运行其测试并执行保证所有测试都通过的规则。

您可以按范围对测试进行分类,以定义何时何地运行哪些测试。例如,遵循 5 层模型

类别

环境(在哪里)

触发器(何时)

单元

[本地][4]

每次提交

组件

本地

每次提交

特性

本地和模拟器

合并前,在合并或提交更改之前

应用

本地、模拟器、1 部手机、1 部折叠屏手机

合并后,在合并或提交更改之后

候选发布版本

8 部不同的手机、1 部折叠屏手机、1 台平板电脑

发布前

  • 单元组件测试在持续集成系统上为每次新的提交运行,但仅针对受影响的模块。
  • 所有单元、组件特性测试在合并或提交更改之前运行。
  • 应用测试在合并后运行。
  • 候选发布版本测试每晚在手机、折叠屏手机和平板电脑上运行。
  • 在发布之前,候选发布版本测试在大量设备上运行。

当测试数量影响生产力时,这些规则可能会随着时间的推移而发生变化。例如,如果您将测试移动到每晚执行,您可能会减少 CI 构建和测试时间,但您也可能会延长反馈循环。