背景
测试是任何软件开发流程中的关键环节。确保应用程序按预期运行、没有缺陷,是向终端用户交付高质量产品的基本要求。本节将探讨测试在开发周期中的重要性,并重点介绍自动化测试流程的优势。
测试是生产流程不可或缺的一部分,务必牢记:你的软件最终一定会被测试,无论是由你、你的自动化测试脚本,还是终端用户来完成。疏于彻底测试产品,可能导致性能低下、出现错误,最终让客户不满。
大多数测试任务简单且重复,非常适合自动化。通过自动化测试流程,你可以节省宝贵的时间和资源、提升准确性,并降低人为错误的可能性(始终牢记:人类并不完美,会犯很多低级错误)。自动化测试还可以按需频繁运行,确保缺陷能被及时发现和处理。
在整个开发周期中,应当实施各种类型的测试,以便尽早发现 Bug 和问题,使其更易于解决。通过结合单元测试、端到端(E2E)测试等不同测试技术,可以确保应用程序在开发的每个阶段都得到全面验证。接下来的章节将探讨标准开发周期,并讨论如何在这一框架内有效地应用自动化测试。
开发周期
敏捷软件开发生命周期(SDLC)的标准工作流通常由几个阶段组成,每个阶段都有其目的和目标,包括:
- 构想:此阶段涉及产生想法、识别机会,以及定义项目目标和需求。
- 开发:包括 UX/UI 设计、架构设计、编码和集成。
- 测试:此阶段涉及验证软件的功能、性能和整体质量。
- 部署:在此阶段,软件被逐步发布到生产环境。
- 运维:最后阶段涉及按需维护和更新软件、解决出现的问题,并根据用户反馈和性能指标持续改进产品。
不同公司可能有其独特的 SDLC 变体,以满足各自的需求和工作流程。在我的团队中,我们的 SDLC 遵循以下结构:
- 撰写 BRD/PRD(业务需求文档/产品需求文档):这些文档概述了项目的目标、宗旨和需求,是后续开发阶段的基础。
- PRD 评审:团队成员(包括开发人员)审查 PRD,从用户和开发者的角度确保设计合理。
- 撰写 TRD(技术需求文档):该文档概述了软件的技术规范和架构,详细说明如何实现产品需求。
- TRD 评审:相关利益方评审技术需求,确保提出的解决方案与项目目标和约束条件一致。
- 实现(前端/后端):开发人员开始编写应用程序代码,专注于前端和后端组件。
- 代码评审:其他团队成员审查代码,确保其遵循最佳实践并满足项目需求。
- 重构:在此阶段对代码进行必要的修改或改进。
- QA 测试:进行质量保证测试,包括手动和自动化测试,确保软件达到预期的质量标准。
- 小流量:将应用程序逐步推送给一小部分用户,密切监控性能和用户反馈。
- 全量流量:软件最终部署给所有目标用户,标志着开发周期的完成。
- 维护:世界上不存在完美的系统,需求也在不断变化。因此我们需要频繁地维护和迭代我们的系统。
手动测试的局限性
尽管开发周期可以产出高质量的产品,但我的团队偶尔仍会遇到 Bug 和故障,其中一些由我自己负责。2023 年 3 月,我们经历了五次故障,虽然没有一次特别严重,但它们凸显了改进的必要性。人为错误不可避免,这正是自动化不可或缺的原因。 让我们来分析一下我团队故障中的一些具体问题。
代码变更与 QA 测试的交叉
理想情况下,测试应始终跟随代码变更进行。然而在实践中,这并不总是可行的。在 QA 测试阶段之后,开发人员还需要修复 Bug、解决合并代码时的冲突等。仅依靠手动测试,整个过程既耗时又消耗资源,反复进行全面 QA 测试变得不切实际。
以我团队故障中的这个例子为例:
- 合并冲突导致路由缺失:快速的产品迭代和同时进行的需求导致频繁的冲突解决。解决冲突可能引入 Bug,尤其是当处理冲突的人只编写了部分代码时。将手动测试聚焦于需求本身,使此类故障得以发生。
对黑盒模块的依赖
我们的系统严重依赖众多外部依赖项。模块化对于构建复杂系统至关重要,但这通常意味着依赖黑盒模块。 信任这些依赖项可能导致 Bug 的产生。
以下是一些故障案例:
- 依赖变更导致产品入口消失:开发人员可能不了解其变更对下游产品的影响。当依赖项发生变化时,让 QA 手动测试所有下游产品是不切实际的。
- 过时的 JS Bridge(JSB)文档导致某些 App 版本功能异常:在开发使用 JSB 的新功能时,要求开发人员或 QA 测试每个 App 版本是不合理的。开发人员相信文档,但当文档过时时,故障就会发生。
组合爆炸
我们的团队服务于全球各地区、语言、平台和 App 版本的用户。功能也有多种组合。可能的组合数量 O(m^n)(A * B * C * D …)是巨大的,且大多数是重复性的。 人类并不擅长这项任务,如以下故障所示:
- 某些地区缺少某个功能:我们团队在多个地区发布了一个功能,但有一个月在某些地区缺失了该功能。简单的原因是没有人在这些地区进行测试。期望 QA 为每个需求单独测试每个地区是不切实际的。
在 SDLC 中应用自动化测试
提升软件开发敏捷性的关键之一是自动化。考虑到手动测试的局限性,我们知道手动工作既耗时又容易出错。因此,我们需要在 SDLC 中融入自动化测试。本节将介绍如何将各种类型的自动化测试应用于 SDLC,并展示它们在预防产品故障和 Bug 方面的有效性。
TRD:编写与评审测试用例
在 TRD 阶段,记录每个新模块的测试用例并让其他开发人员评审至关重要。引入自动化测试后,测试用例提供了一种极佳的方式来描述用户与我们模块的交互。 测试用例可能类似于:”当用户点击某物时,应显示某内容”,或”输入某内容时,应返回某内容”。它们描述了用户(终端用户或开发人员)如何与模块交互,作为代码库中的文档,提升了可维护性。
开发:单元测试与 TDD
在开发过程中,我们为各个单元创建测试脚本,并努力通过每个测试用例。这些测试是我们模块的第一批”用户”。编写单元测试有诸多好处,例如隔离问题、简化排查、测试边界情况,以及复用现有测试确保我们不会意外破坏已有功能。 通过采用测试驱动开发(TDD),你可以从单元测试中获得更多收益。查看我关于 How Testing Speeds Up Your Development 和 Testing Best Practice Tdd 的博文了解更多信息。
集成与测试:E2E 测试
完成前端和后端开发后,我们可以启动端到端(E2E)测试。通过自动化手动测试,我们显著降低了 QA 测试的复杂性。此外,我们可以复用之前的测试用例进行回归测试。这让开发人员能够自信地修改代码和解决冲突,因为 E2E 测试会跟随他们的变更,确保应用程序的整体完整性。
巡检、压力测试、性能测试等
我们可以为生产环境设置 E2E 测试巡检,以尽快发现问题,而不是等待用户反馈。通过实施压力测试和性能测试,我们可以从多个角度评估产品质量,确保最终产品更加健壮和可靠。
结论
总而言之,将自动化测试融入开发周期可以在提升可靠性、可维护性和可扩展性的同时,显著缩短开发时间。通过实施这些测试方法,上述大多数故障都可以得到预防,从而形成更敏捷、更高效的 SDLC。将自动化测试作为开发流程的重要组成部分,最终带来更高质量的产品,以及对开发人员和终端用户都更顺畅的体验。