【译文】谷歌测试技术:多少测试才算足够?

每个软件开发人员和团队都会遇到一个熟悉的问题:”多少测试才足以使软件合格发布?这在很大程度上取决于软件的类型、目的和目标受众。与简单的智能手机手电筒应用程序相比,商业搜索引擎的测试要严格得多。然而,无论何种应用,测试多少才算足够的问题都很难给出明确的答案。更好的办法是提供一些考虑因素或经验法则,用于确定最适合当前情况的鉴定流程和测试策略。以下提示提供了一个有用的标准:

  • 记录您的流程或策略。
  • 拥有坚实的单元测试基础。
  • 不要吝啬集成测试。
  • 对关键用户旅程进行端到端测试。
  • 了解并实施其他层级的测试。
  • 了解代码和功能的覆盖范围。
  • 利用现场反馈改进流程。

记录您的流程或策略

如果您已经在测试产品,请记录整个过程。这对于在以后的版本中重复测试和分析测试结果以进一步改进至关重要。如果这是您的首次发布,最好有一个书面测试计划或策略。事实上,任何产品设计都应该有书面测试计划或策略。

拥有坚实的单元测试基础

编写与代码配套的单元测试是一个很好的开始。单元测试在功能单元级别对编写的代码进行测试。对外部服务的依赖要么是模拟的,要么是伪造的。

模拟与生产依赖具有相同的接口,但只检查对象是否按照预期使用,和/或返回由测试控制的值,而不是完全实现其正常功能。

另一方面,fake 是对依赖关系的浅层实现,但理想情况下它本身不应该有任何依赖关系。假系统提供的功能范围比模拟系统更广,而且应由提供生产版本依赖关系的团队进行维护。这样,随着依赖关系的发展,假模型也会随之发展,单元测试编写者可以确信假模型反映了生产依赖关系的功能。

在包括谷歌在内的许多公司,都有要求任何代码变更都必须有相应的单元测试用例通过的最佳实践。随着代码库的不断扩大,在提交代码前执行单元测试,是在错误侵入代码库之前将其捕获的重要一环。这可以节省日后编写集成测试、调试和验证现有代码修复的时间。

不要吝啬集成测试

随着代码库的增长,功能单元的数量达到了可以作为一组进行测试的程度,这时候就需要有坚实的集成测试基础。集成测试将一小组单元(通常只有两个单元)作为一个整体来测试它们的行为,以验证它们是否能协调一致地工作。

开发人员通常认为,集成测试可以不优先进行,甚至可以跳过,转而进行完整的端到端测试。毕竟,后者才是真正按照用户的使用习惯来测试产品。然而,拥有一套全面的集成测试与拥有坚实的单元测试基础同样重要(参见之前的 Google 博客文章《修复测试沙漏》)。

原因在于集成测试比完整的端到端测试依赖性更小。因此,集成测试需要调用的环境较少,因此会比具有全套依赖关系的完整端到端测试更快、更可靠(请参阅之前的 Google 博客文章:Test Flakiness – One of the Main Challenges of Automated Testing)。

对关键用户旅程进行端到端测试

到目前为止,我们已经讨论了产品组件层面的测试,首先是单个组件的测试(单元测试),然后是组件组和依赖关系的测试(集成测试)。现在是按照用户的使用习惯对产品进行端到端测试的时候了。这一点非常重要,因为需要测试的不仅仅是独立的功能,而是包含各种功能的整个工作流程。在谷歌,这些工作流程(关键目标与用户为实现该目标而执行的任务流程的组合)被称为 “关键用户旅程”(CUJ)。了解 CUJs、记录 CUJs,然后使用端到端测试(最好是自动化测试)对 CUJs 进行验证,就完成了测试金字塔(Testing Pyramid)。

了解并实施其他层级的测试

单元测试、集成测试和端到端测试针对的是产品的功能层面。了解其他层级的测试非常重要,包括

  • 性能测试 – 测量应用程序或服务的延迟或吞吐量。
  • 负载和可扩展性测试 – 在负载越来越高的情况下测试应用程序或服务。
  • 容错测试–测试应用程序在不同依赖关系失效或完全瘫痪时的行为。
  • 安全测试 – 测试服务或应用程序中的已知漏洞。
  • 可访问性测试–确保产品可供所有人访问和使用,包括各种残障人士。
  • 本地化测试 – 确保产品可在特定语言或地区使用。
  • 全球化测试 – 确保世界各地的人都能使用产品。
  • 隐私测试–评估并降低产品中的隐私风险。
  • 可用性测试–测试用户友好性。

同样,在审查周期内尽早进行这些测试过程也很重要。较小的性能测试可以更早地发现问题,节省端到端测试的调试时间。

了解代码和功能的覆盖范围

到目前为止,我们已经从定性的角度研究了多少测试才算足够的问题。我们回顾了不同类型的测试,并提出了 “越早越好,越小越好,越大越好,越晚越好 “的观点。现在,我们将从定量的角度,结合代码覆盖率技术来研究这个问题。

维基百科上有一篇关于代码覆盖率的文章,概述并讨论了不同类型的覆盖率,包括语句覆盖率、边缘覆盖率、分支覆盖率和条件覆盖率。对于大多数流行的编程语言,如 Java、C++、Go 和 Python,有几种开源工具可用于测量覆盖率。下表列出了部分工具:

Language Tool
Java JaCoCo
Java JCov
Java OpenClover
Python Coverage.py
C++ Bullseye
Go Built in coverage support (go -cover)

表 1 – 不同语言的开源覆盖工具
这些工具大多提供百分比总结。例如,80% 的代码覆盖率意味着大约 80% 的代码被覆盖,大约 20% 的代码未被覆盖。与此同时,重要的是要明白,仅仅因为你覆盖了代码的某一特定区域,该代码仍然可能存在错误。

覆盖率的另一个概念叫做变更列表覆盖率。更改列表覆盖率衡量的是已更改或已添加行的覆盖率。它适用于积累了技术债务、整个代码库覆盖率较低的团队。这些团队可以制定一项政策,通过增加增量覆盖率来提高整体覆盖率。

到目前为止,覆盖率的讨论主要围绕测试代码的覆盖率(函数、行等)。另一种覆盖率是特征覆盖率或行为覆盖率。对于功能覆盖,重点是识别特定版本中已提交的功能,并为其实现创建测试。对于行为覆盖,重点是识别 CUJ 并创建适当的测试来跟踪它们。同样,了解 “未覆盖 “的功能和行为也是了解风险的有用指标。

利用现场反馈改进流程

了解和改进鉴定流程的一个非常重要的部分是软件发布后从现场收到的反馈。以行动项目的形式跟踪故障、错误和其他问题,以改进鉴定流程,这对于最大限度地降低后续版本中的回归风险至关重要。此外,这些行动项目应:(1) 强调在鉴定过程中尽早填补测试缺口;(2) 解决战略问题,如缺乏特定类型的测试,如负载或容错测试。同样,这也是为什么必须记录认证流程的原因,以便根据从现场获得的数据重新评估。

总结

制定全面的鉴定流程和测试策略来回答 “多少测试才算足够 “的问题,可能是一项复杂的任务。希望这里给出的建议能对您有所帮助。总结:

  • 记录您的流程或策略。
  • 拥有坚实的单元测试基础。
  • 不要吝啬集成测试。
  • 对关键用户旅程进行端到端测试。
  • 了解并实施其他层级的测试。
  • 了解代码和功能的覆盖范围。
  • 利用现场反馈改进流程。

本文文字及图片出自 How Much Testing is Enough?

余下全文(1/3)
分享这篇文章:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注