你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于此 Azure Well-Architected 框架卓越运营清单建议:
| OE:09 | 通过采用符合业务目标并维护质量标准的测试做法来提高工作负荷的质量。 |
|---|
在引入对工作负荷的更改时,需要确保其按预期工作,不会引入新问题。 测试是评估这些更改的方式。 这是维护质量和增强工作负荷信心的基本做法。
有效的测试提供可靠的高质量工作负载。 它可以防止缺陷到达生产,减少成本高昂的返工和延迟,并使你的工作与整个开发生命周期的业务目标保持一致。
本文提供了一些策略,可帮助你通过有效的测试做法提供高质量的工作负荷。 它充当其他支柱(如性能、可靠性和安全性)中专用测试指南的基础指导。
有关测试实践的实现指南,请参阅配套文章:使用有效的测试实践增强对Azure工作负荷的信心。
正式化测试策略和计划
您的测试策略和测试计划是关键文档。 他们为测试工作提供了明确的路线图,并确保每个人都致力于相同的质量目标。
定义测试策略
测试策略是指导总体测试方法的高级蓝图。 它定义测试目标、范围、方法、工具、角色和职责。 它有助于做出有关测试优先级、资源分配和风险管理的明智决策。 它还反映了与利益相关者的沟通和结果的报告方式。
明确定义的测试策略能够获得利益相关者的认同,并确保所有团队成员遵循一致的质量标准。 它提供方向和结构,使测试与业务目标保持一致,并保护长期质量。
测试策略通常会在给定工作负荷的各版本中保持一致。 但始终对其进行自定义,以反映该工作负荷的特定需求和业务目标。
注释
不要对不同的工作负荷应用相同的标准化策略。 它们有独特的注意事项,因此需要独特的方法。
创建计划
与团队就测试策略达成一致后,请在测试计划中正式化该策略,并将用例与业务目标保持一致。
测试计划是指导特定版本的测试执行的详细文档。 它概述了测试范围、特定测试用例、缺陷报告、时间线、资源分配以及测试活动的进入和退出条件。
结构良好的测试计划使测试高效且与发布目标和时间线保持一致。 它是跟踪进度和在整个测试过程中做出明智的决策的参考点。
例子: 对于电子商务结帐系统,测试策略定义付款流始终处于优先顺序,为系统指定测试工具,例如用于负载测试的 JMeter。 它阐明了不同测试类型的团队职责。
发布的测试计划侧重于添加 Apple Pay 支持。 它确切地定义了在此版本中测试 Apple Pay 的内容、分配资源(两个工程师和三个 iOS 设备)、设置四周的计划,并建立明确的入口条件(代码完成和环境配置)和退出条件(所有测试通过和零关键 bug)。
注释
在明确定义总体测试策略和计划之前,请勿开始测试。 可靠的测试计划使你的工作保持专注,并与工作负荷目标保持一致。
提前测试,经常测试,测试重要事项
在软件开发生命周期的最早阶段开始测试。 若很晚才发现关键问题,你将面临返工增多以及拖慢发布速度的问题。 架构师经常会忽略设计阶段的测试要求,这会对整体质量产生负面影响。
开发人员应采用质量保证思维模式。 在设计阶段考虑进行测试。 使用它来阐明要求并发现潜在的限制。 使测试成为开发过程不可或缺的一部分。 负责编写和维护与代码相关的测试。
提前检测问题时,可以快速响应。 例如,可以优先处理影响用户体验的至关重要的设计更改,而不是例行的 bug 修复。 提前行动减少了最后一分钟的惊喜和延误。
测试不是一次性事件。 作为持续测试思维模式的一部分,在启动后继续进行测试。 定期查看、更新和扩展测试套件,以涵盖在生产中发现的新功能并解决 Bug,以保持长期质量。
注释
在交付周期后期,不要延迟大型批处理的测试。 延迟测试会导致问题遗漏、返工增多和发布进度拖慢。
权衡。早期和持续测试可能会增加运营成本,并且最初可能会降低开发速度或产生团队内部的摩擦。 设法找到一个平衡,确定哪些测试和更改在早期阶段是必要的,以及哪些可以推迟到后续阶段。 这可以确保效率,而不会损害质量。
使用安全措施在生产中进行测试
即使在强大的测试和验证实践中,一些问题也仅在实际生产流量下出现。 若要查找无法模拟的问题,请在生产中执行受控测试,并保护用户暴露并降低风险。
规划、隔离和监视每个生产测试。 执行此操作时,可以获得真正的用户反馈和性能数据,而不会中断其他人。
考虑渐进式曝光策略(例如 Canary 发布),仅在工作负荷满足退出条件并表现出强大的质量之后。 此方法首先向一小组目标用户发布更新,帮助你快速发现可能不会出现在预发布环境中的问题。 使用此方法,可以加速测试过程,并可能降低相关的成本。
持续监视生产测试 ,以尽早发现问题。 实现自动化安全措施,以便在测试对用户造成负面影响时停止测试,例如自动回滚机制和实时警报。 这些技术可确保快速响应并最大程度地减少中断。
风险: 在生产环境中进行测试时要谨慎,因为它直接影响到真正的客户。 始终实施安全措施和限制暴露,以最大程度地减少对企业的潜在负面影响。
在测试覆盖范围中应用分层方法
分层测试覆盖率策略提供快速反馈、早期缺陷检测和更快的发布。 在层中构建测试时,可以快速隔离和调试缺陷,从而更轻松地查明和解决问题。
使用测试棱锥图作为指南
测试棱锥模型演示了这种分层的测试自动化方法。 它将测试分布到不同的层,以最大程度地提高覆盖范围,同时最大程度地减少执行时间和维护成本。
- 基本层:单元测试以隔离的方式验证各个组件。 它们快速运行,并提供即时反馈。
- 中间层:集成测试验证组件和服务之间的交互。 它们运行速度比单元测试慢,但提供系统行为的更广泛覆盖。
- 顶层:端到端测试验证整个系统的用户旅程,模拟真实场景。 这些测试运行速度最慢,但对整体质量具有最高置信度。
可以更轻松地将基本层和中间层测试集成到管道中,因为它们具有最少的依赖项。 当测试失败时,此集成可实现快速反馈,并允许生成进程立即停止,从而防止错误代码进一步推进。
随着测试覆盖率的增长,管道执行时间可能会显著增加。 使用并行和分布式测试执行策略保持快速反馈循环,即使覆盖范围增加,管道也保持高效。
注释
不要在编译和验证代码的初始生成管道中包含每个可能的测试。 此选项会减缓发布周期,并有可能绕过重要的测试。 专注于直接保护关键工作流的测试,并提供对系统质量有意义的置信度。
权衡。 测试覆盖率与管道效率之间存在权衡。 虽然较大的测试套件会增加覆盖范围,但它们也会增加执行时间和成本。 它们并不总是提供有意义的投资回报。
单独的应用程序和基础结构测试
在测试应用程序代码和基础结构代码之间创建明确的分段。
将测试与验证内容和拥有者分开,然后添加集成测试,以确认这两个层协同工作。 应用程序代码测试应侧重于验证工作负荷的行为。 基础结构代码测试应侧重于验证基础结构的预配和配置。
添加跨层测试,以一起练习应用程序和基础结构。 基础结构测试本身可以提供虚假的信心。 IaC 模块可能会正确预配每个资源,但如果应用程序实际上无法使用这些资源,则工作负荷仍会失败。 通过部署软件并对其运行测试来观察应用程序行为来验证基础结构。 针对运行状况终结点的简单冒烟测试可快速捕获这种差距。
合并不同类型的测试
在整个工作负荷中使用各种测试方法。 完成单元测试并不意味着已完成测试。 工作负荷的各个方面都需要一种不同的方法。 多个测试类型可增强整体质量,并建立系统按预期运行的信心。
为作业使用正确的工具。 确定执行各种类型的测试所需的工具。 如果没有工具,请购买该工具。 不要构建它,因为这可能会引入风险。 研究工具及其功能,例如许可成本,以及这些工具是否直接与工作负载要求集成。 通过进行概念验证,评估团队对各个工具的熟悉程度,并考虑兼容性和集成情况。 如果负责该工作负载的团队不具备相关专长,请充分利用这些工具可获得的支持和培训。
根据工作负荷成熟度和风险配置文件选择正确的测试类型。 首先通过测试棱锥层进行功能验证,然后添加性能、安全性和复原能力等非功能测试。 使测试类型选择与工作负荷的关键方案和风险保持一致。
下表显示了何时在整个测试周期中应用不同的测试类型。 每个都解决了特定风险。 虽然此表并非所有可能的测试类型的详尽列表,但它充当演示示例。
| 测试类型 | 主要用途 | 适用情况 | 成本与注意事项 |
|---|---|---|---|
| 手动测试 | 验证需要人工判断、探索学习、可用性和 UX 细微差别的方案。 | 早期开发、UI 更改、模糊流或自动化不可行时。 | 高成本、低可伸缩性 - 谨慎使用并专注于人类见解增加不可替代价值的领域。 |
| 单元测试 | 隔离验证单个组件或函数逻辑。 | 在开发过程中持续。 | 成本最低且值最高 - 快速、可靠且对于防止回归至关重要。 旨在广泛覆盖。 |
| 集成测试 | 验证组件、API、协定和共享服务之间的交互。 | 当组件和服务准备好交互或集成新依赖项时。 | 中等成本 - 早期捕获错误配置和交互缺陷至关重要。 |
| 契约测试 | 验证服务是否仍满足其使用者所依赖的交互,而无需完整的集成测试。 | 更改其他团队或服务所依赖的 API 时,尤其是在独立的发布周期中。 | 中等成本 - 存在有助于记录使用者期望并在自己的管道中作为测试重播的框架。 |
| 端到端 (E2E) 测试 | 确认整个系统的完整工作流正确性,从用户操作到后端服务。 | 核心用户旅程稳定且能够自动化时。 | 高成本和易碎 - 选择性地对大多数业务关键流使用。 |
| UI 测试 | 检测视觉效果、布局和交互回归问题。 | 当 UI 设计趋于稳定或视觉效果要求达到发布标准时。 | 高维护成本 - 限制为关键 UI 路径和辅助功能关键方案。 |
| 负载和性能测试 | 在预期的工作负荷下验证性能、延迟、吞吐量和可伸缩性。 | 尽早开始,并随着体系结构的发展而重复。 | 成本虽高,但对于生产就绪(尤其是面向客户的工作负载)来说是必不可少的。 |
| 压力测试 | 确定系统限制、断点和恢复行为。 | 在生产就绪或主要体系结构更改之前。 | 高成本,提供复原见解 - 由于环境影响,有选择地运行。 |
| 安全测试 | 识别漏洞、配置错误和攻击途径。 | 在整个开发生命周期内应用。 | 中高成本但价值非常高 - 保护数据、满足合规性和降低业务风险至关重要。 |
组合不同的测试类型,以从多个角度评估工作负荷。 运行混合,以便捕获任何一个测试都会错过的问题。
根据业务影响和风险确定测试类型的优先级。 根据每项功能的潜在影响和相关风险评估或更改。 对于面向客户的工作负载,请强调端到端和 UI 测试。 对于 API 驱动的工作负载,请专注于集成和协定测试。 对于高可用性系统,请投资于弹性和混沌测试。
权衡。 在发布过程开始时确定安全测试的优先级。 此方法有助于防止漏洞并确保更安全的部署。 但是,此优先级可能会降低向生产交付新功能的速度。
将测试资产视为与代码资产一样重要
测试资产可捕获重要的业务规则、边缘案例、历史缺陷模式以及有价值的组织知识。 当测试质量下降时,团队会浪费时间调试不可靠的测试,而不是发现真正的缺陷。 这种情况会造成挫折感,开发人员在测试框架中失去信任。
像对待代码资产一样严格对待测试资产。 完全负责测试资产可增强测试框架的可靠性和整体质量。
组织和确保安全的测试
使用与您的应用程序代码相同的架构原则来组织测试代码。
将测试与代码一起保存在同一存储库中 ,以简化维护和提升一致性。
实施等效的治理控制措施 ,例如强制代码评审、拉取请求策略和生成验证管道,以维持质量标准。
将测试数据与代码一同进行版本控制。 更改数据架构或业务规则时,更新测试数据以匹配当前工作负荷状态。
对自己的测试进行基线验证 ,以确保它们按预期工作。 任何故障都应指向实际应用程序问题,而不是测试缺陷。 验证在工作负载正常时,测试能否适当失败并一致通过。 及时解决不可靠的测试问题,并确保测试断言强化每个测试的意图。
设置确保测试独立性和可靠性的做法,例如隔离测试数据、避免共享状态,并实现自动设置和拆解过程。
设计并行执行测试。 为了受益于并行测试执行,请将测试设计为独立测试,以便它们可以按任何顺序运行,而不会影响结果。 独立测试应始终初始化和清理自己的数据和依赖项,以防状态影响后续测试。
如果应用程序需要在测试中排序,请使用支持有序测试执行的测试框架。
- 在测试代码中实施安全编码做法,以防止漏洞。 测试通常与生产数据和系统交互,这可能会给导入的库或易受攻击的测试代码带来风险。 使用与生产代码相同的安全标准处理测试。
使测试资产与当前使用模式保持一致
性能测试资产包含有关工作负荷的预期行为、可接受的性能阈值和实际流量模式的关键知识。
按类型组织测试套件。 在单独的套件中保留负载测试、压力测试和耐力测试。 不要混合它们。 每种类型都有不同的设置要求、运行持续时间和成功条件。 组织套件可以更轻松地运行目标测试、跨运行比较结果以及独立维护每个套件。
定期刷新测试数据。 过时的测试数据会导致不切实际的结果。 重新生成测试数据,以在数据模型发生更改、数据量增长或用户人口统计变化时反映当前生产数据特征。
随着工作负荷的发展,请查看测试方案。 计划定期评审,以确保方案仍反映实际使用情况。
测试数据应类似于实际生产数据。 使用具有生产数据特征的合成数据。 为某些方案预留生产数据集(经过正确匿名处理),例如突出显示数据管理行为,如事务一致性、数据量处理和延迟。
维护和改进测试
维护测试资产对于保持工作负荷质量至关重要。 这些资产通常包含有价值的组织知识。 如果不定期维护它们,它们很快就会过时,破坏了其有效性和提供高质量版本的能力。
随着工作负荷的发展,测试资产必须并行发展,以便与业务目标保持一致。
从小规模开始,有意识地扩大回归套件。 回归测试套件应包含最有价值的稳定测试。 在发生生产事件、修复关键 bug 以及引入高风险更改时添加测试。
自动执行回归套件 ,使其一致运行,而无需人工干预。 创建快速冒烟测试,在每次提交时运行;创建更广泛的回归测试以在每晚或发布前运行。
使测试自动化脚本和测试用例保持同步。 测试用例捕获意向、范围和预期结果。 如果自动化脚本与其相应的测试用例不同,则很难跟踪正在验证的内容,从而导致覆盖和问责方面的差距。
在为工作负荷引入新功能和增强功能时,主动计划对测试用例的定期更新。 自动执行测试用例时,请将自动化链接到原始测试用例,以便跟踪覆盖范围。
管理测试技术债务
定期进行测试维护冲刺,以解决技术债务,防止其演变为难以承受的负担。 不稳定的测试、重复测试覆盖、过时的测试以及测试设计不佳都会导致测试债务。
确定修复或删除不可靠的测试的优先级 ,以保持测试套件的完整性。 一组较小的可靠测试比一组大量的易出错测试更有价值。
制定有关跳过或延迟测试的战略决策。 请考虑跳过对简单代码或低风险代码的测试,例如没有业务逻辑的简单 getter 和 setter、极其罕见的边缘案例、第三方库和计划删除的旧代码。 记录这些决策,以便团队可以在上下文更改时重新访问这些决策。
评估测试套件,并将可靠且一致的测试与那些容易发生外部更改的测试分开。 由于一些不可控的因素(例如频繁的UI更新影响到的UI测试)而经常中断的测试,可能不适合作为自动化测试的候选者。 这种分离可帮助你确定要自动执行哪些测试,以及哪些测试需要手动执行。
权衡。删除不稳定的测试会降低自动化覆盖范围。 通过将自动化集中在稳定接口和关键工作流上以平衡工作量的削减,并为经常更改的 UI 元素接受手动测试。
并非所有测试都值得持续维护。 停用你删除的功能的测试、重复覆盖率的测试,以及不再提供价值的测试。 记录你删除测试的原因,以便决定对团队清楚。
将可观测性扩展到测试框架
测试中的可观测性提供了两个关键优势。 首先,它确认测试框架是否正常工作。 其次,它使你能够持续了解工作负荷的质量和运行状况。
如果没有这种可见性,你将面临相当大的诊断问题、实时监视系统的能力有限,并且你无法清楚地了解自动化覆盖率的有效性。
测试套件会随着时间推移而恶化。 测试变得不可靠、失去相关性或无法跟上工作负荷更改。 通过整合可观测性,可以有效地监视测试套件的运行状况,快速查明和解决故障,并做出有关维护优先级和改进的明智决策。
生成覆盖率报告以识别自动化中的差距。 当测试覆盖率与生产事件的可观测性数据保持一致时,团队可以深入了解哪些方案缺乏足够的验证。
在您的框架中使用行业标准的测试覆盖率和报告工具,以:
- 提供对测试代码路径的清晰可见性
- 确定一致失败的测试
- 分析测试可靠性的长期趋势
- 跟踪针对目标改进的故障来源
风险: 如果日志不一致且过于详细,则它们可能会产生比值更多的干扰,从而使调试更加困难。 使用清晰、可操作的消息和不同的日志详细级别实现结构化日志记录,以确保日志提供有意义的见解,而不会使团队感到过于繁重。
模拟现实情况
从最终用户的角度评估工作流,确保他们真正满足客户需求和期望。 为工作负载定义明确的验收标准,并设计能够准确反映真实用户流和体验的测试,而不仅仅是独立的系统行为。
从战略上缩放覆盖范围
根据风险和价值缩放测试覆盖率。 确定高价值用户旅程和直接影响客户体验的关键路径的覆盖优先级。 随着工作负荷复杂性的增长,通过评估对工作负荷质量和可靠性提供最高置信度的方案来扩展测试覆盖范围。
风险: 不要在单个用户流入中进行超过收益递减点的过度投资。 为关键路径实现足够的覆盖范围后,将焦点转移到其他重要区域。 力求平衡覆盖,而不是追求在一个流程中完美无缺。
与业务目标和 SLO 保持一致
将测试与业务目标和服务级别目标(SLO)保持一致。
设置可衡量的质量阈值,以反映业务承诺和用户期望。 同意这些阈值,因为它们提供一个参考点来检测偏差并排查错误。 此方法通过确保关键服务质量阈值不会泄露来保护用户体验。
定期查看和更新基线指标,确保它们继续满足当前的客户需求和预期。
使用具有代表性的测试数据
测试数据应尽可能接近实际方案。
综合数据可以模拟真实的用户方案,同时避免生产数据处理的复杂性。 例如,综合测试可以通过生成具有代表性的数据集来复制实际方案,以评估工作负荷在计划内缩放条件下的表现。
使用综合数据作为默认选择。 对于合成数据无法复制必要复杂性(例如测试数据迁移脚本)的特定场景,可以保留生产数据。
如果需要使用生产数据进行测试,请确保正确匿名化所有信息以保护敏感信息。
模拟生产环境
生产环境是了解工作负载在实际条件下行为方式的真相来源。 创建一个环境,以密切反映实际条件,以便可以信任系统在生产环境中按预期方式执行。
- 定制用于将 生产环境镜像到工作负荷的特定需求的方法。
对于需要高可用性的任务关键型工作负荷,在与生产密切相关的专用环境中进行测试。 对于这些工作任务,请谨慎权衡成本优化与健全验证之间的需求。
使用专用的生产型环境进行性能和负载测试,以确保在现实条件下准确评估服务行为。
对于其他工作负荷,使环境密切反映生产基础结构,以减少误报,例如测试在较低环境中成功但生产失败的情况。
在代码通过管道推进时,实现所有环境的一致性。 模拟工作负荷的各个方面(包括基础结构、数据和安全性)的生产条件,以确保可靠的测试结果。
防止配置偏差。 将环境复制到生产环境时,配置偏移可能会引发对质量的错误信心。 实现配置偏移的自动验证检查,确保环境与生产保持一致。 在适当情况下,设置部署入口以在测试开始之前验证是否已部署正确的版本。
风险: 镜像生产环境时,它可以显著增加运营成本。 评估临时环境还是持久性测试环境是否为工作负荷提供成本效益和质量之间的最佳平衡。
构建以目的为导向的测试环境
设计环境时要明确关注其预期目的。 评估测试生命周期中每个阶段的不同要求,并确保环境与该阶段的目标保持一致。
有意设计每个测试环境以匹配特定阶段和测试目标,无论是出于功能验证、集成测试还是其他目的。 如果简化的环境有效地满足测试需求,请确定这种方法的优先级,以最大限度地提高效率。
使用模拟服务
对于每个测试方案,生产系统的完整复制通常是不切实际的。 评估可以安全复制的工作负载的哪些组件进行测试,而不会影响关键业务工作流。 如果完全复制不可行,请使用可准确模拟生产服务行为的模拟服务来有效验证方案,而不会危及实时操作。
目的驱动测试环境为在临时环境中部署模拟服务提供了理想的基础。 临时环境提供了一种经济高效的方法来模拟用于测试的生产条件。 可以验证交互和行为,消除为每个测试方案维护完全类生产环境的开销。 这些按需环境是为特定测试目的创建的,在使用后销毁,同时降低基础结构成本,同时保持测试质量。
要构建短暂性环境,您的工作流程需要达到较高的成熟度级别,在此成熟度级别上,已建立良好的基础设施即代码(IaC)和部署流水线自动化。
Azure 协助
Azure 测试计划 是基于浏览器的测试管理解决方案,提供计划内手动测试、用户验收测试、探索性测试以及收集利益干系人反馈所需的所有功能。 它包括 测试分析 ,用于跟踪一段时间内的测试质量,并确定要改进的领域。
Azure Pipelines 使你能够将测试集成到 CI/CD 管道中。 还可以使用与 Azure 集成的 GitHub Actions 。
Azure 应用测试 是一项支持功能和性能测试的服务。 它允许您使用 Playwright 工作区运行功能测试,并通过 Azure 负载测试进行性能测试。
Azure 部署环境 有助于使用基于项目的模板来启动应用基础结构,这些模板可建立一致性和最佳做法,同时最大程度地提高安全性。
Azure 还提供支持可靠性、性能和安全测试的平台原生工具。
相关链接
卓越运营清单
请参阅完整的建议集。