自动化性能测试
性能测试自动化是建立一个可重复且一致的流程,用于在开发和发布周期的不同阶段检查可靠性问题。例如,您可以从 CI/CD 流水线和夜间作业中运行性能测试,或者手动触发负载测试并实时监控其影响。
在性能测试中,自动化并不能取代手动运行测试的需求。它关乎将性能测试作为软件开发生命周期 (SDLC) 的一部分进行规划,以实现持续性能测试。
本指南提供通用建议,帮助您规划和定义运行自动化性能测试的策略
- 哪些测试应自动化?
- 应测试哪个环境?
- 测试频率如何以及如何运行测试?
- 如何分析性能结果?
请注意,本指南假设您熟悉 k6 并已具备性能测试。如果您是性能测试或 k6 的新手,建议查阅我们的入门资源。
在我们深入探讨之前,让我们考虑自动化的“原因”以及它如何充分发挥性能测试的优势。
为什么要自动化性能测试
无论是网站在不到一秒内加载,API 在毫秒内响应,还是故障即时响应,性能都至关重要,因为它直接影响最终用户体验。然而,一个组织挑战是性能往往未能获得与功能或需求同等的重视。
在许多组织中,性能仍然是无形的,只有当坏事发生时才会做出反应。自动化改变了这种方法——从被动变为主动。
在性能测试中,建立例程以保持实践的一致性至关重要。自动化对于形成性能测试习惯并提升其部分益处是必要的,包括
- 提高测试覆盖率、信心和维护效率:自动化为各种类型的测试创建了一个持续且迭代的过程。这种持续的性能测试努力可以扩大测试覆盖率、增强测试维护并提高对测试结果的信心。
- 更早检测问题:将性能测试自动化作为软件交付过程的一部分,可以确保应用达到可靠性目标,同时在 SDLC 的早期捕获问题。
- 跨团队协作:自动化促使团队在整个 SDLC 和部门之间制定策略和计划。它鼓励工程领导者倡导可靠性并实施共享实践。
没有自动化,缺乏共享框架常常导致孤立和零星的活动。自动化有助于推动持续的性能和可靠性测试,引入了更高效且有效的测试过程。
不仅仅是 CI/CD
自动化通常指在 CI/CD 流水线中将测试作为发布过程的一部分运行,并带有通过/失败条件。然而,并非所有性能测试都适合 CI/CD 工作流,它们也并非仅仅是提供通过/失败(绿色/红色)状态并充当发布守门人。
将自动化集成到 CI/CD 流水线中是一个选项,但并非调度性能测试执行的唯一方法。创建性能测试计划时,记住有不同的方式可以频繁运行性能测试
- Cron 和 cron 作业运行器。
- 云测试工具,例如在 Grafana Cloud k6 中调度测试。
- 具有自动化功能的测试管理工具。
- 触发手动测试。将其作为发布清单过程中的一步。
仅通过 CI/CD 工具在软件更改上运行测试会限制我们性能测试的目标。一个完整的性能测试策略可以包含 CI/CD 测试、基于 cron 的测试,甚至手动测试,以解决各种测试目的
确定测试目的
该过程的第一步是审查您现有或计划的测试,并了解每个测试的目的。如果定期执行,测试是否可以服务于其他目的?一些常见目标是
- 将当前性能与现有性能基准进行比较。
- 了解关键性能指标随时间的变化。观察平稳或变化的趋势。
- 检测新版本的回归。
- 定期测试服务等级目标 (SLO)。
- 在发布过程中测试关键区域。
- 在 CI/CD 流水线中设置质量门。
当考虑每个测试的一致和持续目的时,您会发现哪些测试需要自动化,哪些功能缺失,以及测试套件中缺少哪些测试。它还会指导您确定运行每个测试的最佳时间和方式。
选择哪些测试需要自动化
性能测试通常可以分为两个方面
- 测试场景(测试用例):测试验证什么?
- 测试工作负载(测试负载):多少流量和什么流量模式?
您的测试套件应包含各种测试,能够使用不同的负载测试类型验证您系统的关键区域。
您希望频繁运行的任何现有测试都是自动化的候选。从根本上说,自动化就是频繁且一致地运行测试,无论是每天、每周还是每年。
为自动化设计性能测试套件时,请考虑两个关键点:从小处着手,并模块化您的测试。
- 从小处着手并迭代:随着团队学习和遇到需要调查的可靠性问题,您的测试套件以及随之而来的测试覆盖率将不断扩展。
- 模块化您的测试套件:在 k6 中,您可以分离场景和工作负载逻辑,并在不同测试中重用它们。这简化了为不同目的创建具有各种流量模式的测试的过程。模块化还允许在多个测试中重用通用逻辑。
在规划测试覆盖率或自动化时,考虑从以下测试开始
- 验证对产品和业务至关重要的核心功能。
- 在高流量场景下评估性能。
- 跟踪关键性能指标,观察其趋势并与基线进行比较。
- 使用通过/失败标准验证可靠性目标或 SLO。
建模场景和工作负载
选择一个或多个测试后,您应该确定需要测试的各种流量类型。
让我们用两个简单的测试来说明一个例子:一个测试评估 GET 端点的性能,另一个测试验证结账流程。
下一步是确定被测系统 (SUT) 为这些测试处理的流量。在这种情况下,我们可以利用我们的分析和监控工具来找到 GET 端点和结账流程的典型流量模式。
根据流量类型,我们可以创建不同类型的测试
在我们的示例中,我们为这两个场景确定了以下工作负载
测试场景 | 冒烟测试 | 平均负载 | 压力测试 | 尖峰测试 | 稳定性测试 |
---|---|---|---|---|---|
GET 端点 | 1 次迭代 | 100 请求/秒 - 3 分钟 | 1500 请求/秒 - 5 分钟 | ||
结账流程 | 3 次迭代 | 50 VU - 5 分钟 | 200 VU - 1 分钟 |
我们建议始终创建用于基线比较的平均负载测试,以及用于在执行大型测试之前验证测试脚本错误的冒烟测试。
在我们的示例中,我们有使用相同测试场景但工作负载不同的测试。这种模式非常常见。在这种情况下,跨测试重用场景逻辑的能力简化了测试创建和维护。一种常见的组织测试模式是使用工作负载类型作为前缀
smoke-get-api.js
:导入通用场景并设置 1 次迭代。load-get-api.js
:导入通用场景并设置 3 分钟内 100 请求/秒。stress-get-api.js
:导入通用场景并设置 3 分钟内 1500 请求/秒。
要了解更多关于在 k6 中配置工作负载的信息,请参阅场景。
决定每个环境的测试频率
下一步是决定测试哪个环境及其频率。每个组织都有不同的环境,它们的目的可能也因组织而异。
以下是一些组织中常见的环境,以及通常用于这些环境的测试类型的一般准则。
开发环境
此环境,无论是个人机器还是其专用环境,可能不包含系统的所有组件。它通常用于在将应用部署到更全面的环境之前进行初步测试。
此环境非常适合通过运行冒烟测试来验证我们测试的基本功能。
在此类环境中,构建和调试性能测试比任何自动化类型更常见。但是,如果您的项目结构允许,您也可以在项目更改时调度冒烟测试的执行。
QA 环境
此环境通常部署整个应用,但基础设施资源最少。它就像一个低规模的预演环境,所有团队都可以用来测试功能方面并查找新功能的回归问题。
鉴于基础设施与生产环境不完全匹配,这种类型的 QA 环境不适合评估应用的性能和可扩展性。
但是,在此环境中通过冒烟测试验证我们测试的功能方面有助于更早地捕获错误。此外,它验证了同一脚本稍后可以在大型负载测试中运行。
运行所有可用的冒烟测试:端到端、集成和单元测试类型。将这些测试作为 CI 流程中执行的自动化测试套件的一部分进行调度。
预发布环境和临时环境
这些环境可用于测试即将发布的版本,每个组织都根据其独特的发布流程以不同的方式使用它们。
作为预发布环境的一般规则,我们应该运行带有质量门的更大规模测试,这些质量门是验证 SLO 或可靠性目标的通过/失败标准。在 k6 中,您可以使用 options
中的阈值来实现,如下所示
export const options = {
thresholds: {
// http errors should be less than 1%
'http_req_failed': ['rate<0.01'],
// 90% of requests should be below 600ms
'http_req_duration': ['p(90)<600'],
// 95% of requests tagged as static content should be below 200ms
'http_req_duration{type:staticContent}': ['p(99)<250'],
// the error rate of my custom metric should be below 5%
'my_custom_metric': ['rate<0.05'],
},
};
然而,有效评估所有可靠性目标可能具有挑战性。您经常会遇到使用不同负载类型进行测试时的“误报”和“真阴性”。
对于大型测试,仅基于通过/失败状态验证发布可能会在您的性能测试和发布过程中造成一种虚假的安全感。
我们建议将预发布环境保留几个小时或几天,以便彻底测试整个系统。我们的建议包括
- 分配一到几天的时间用于验证发布。
- 执行所有现有的平均负载、压力和尖峰测试。
- 连续执行每个测试至少两次。
- 定期(例如,每 4 小时或 8 小时)调度所有测试运行。
Staging/预生产
在某些情况下,staging 环境的角色类似于“预发布”环境。如果是这样,请遵循上一节中提到的策略。
staging 环境始终可用,并持续更新到最新更改。它通常适用于评估性能变化,例如性能趋势、回归或改进。
在这种情况下,我们应该选择评估关键性能指标的测试,并安排它们持续执行,以便在一段时间内收集指标。首先选择几个测试,并安排每周运行两到三次。
与预发布环境一样,我们建议连续执行每个测试至少两次,以便我们可以忽略不可靠的测试。
由于我们旨在发现性能变化,请考虑根据 staging 基础设施扩展测试的工作负载,因为 staging 基础设施通常与生产环境的规模不匹配。
生产环境
通常,先前的测试环境并不能完美地反映生产环境,在测试数据、基础设施资源和扩展策略方面存在差异。
在生产环境中进行测试可以提供在其他环境中无法获得的真实世界洞察。然而,生产测试需要仔细处理和存储生产中的测试数据,并避免影响真实用户。
一种低风险的常见做法是使用冒烟测试进行合成测试,也称为合成监控。以最小负载测试生产环境是安全的。每五分钟调度一次冒烟测试,建立通过/失败测试条件和有效的告警机制。例如,如果连续六次测试运行失败,则发送告警。
如果存在 Blue/Green 或 Canary 部署等发布策略,则针对 Green 或新版本运行负载测试以验证发布。这是观察 SLO 在生产环境中行为的理想时机。
此外,考虑在夜间或系统处理较少流量时调度测试。目标不是给系统施加压力,而是持续收集性能结果,以便比较变化和分析性能趋势。例如,每周调度一次平均流量水平一半的测试。
示例计划
测试 | 部署环境。 | 类型 | 工作负载 | 自动化 | 频率 |
---|---|---|---|---|---|
结账流程 | QA | 冒烟测试 | 1 次迭代 | CI 流 | 分支变更 |
结账流程 | 预发布 | 平均负载 | 50 VU - 5 分钟 | 在 QA/预发布期间调度 | 预发布期间每天 3 次 |
结账流程 | 预发布 | 尖峰测试 | 200 VU - 1 分钟 | 在 QA/预发布期间调度 | 预发布期间每天 3 次 |
结账流程 | Staging | 平均负载 | 50 VU - 5 分钟 | 调度 | 每周 2 次 |
GET 端点 | QA | 冒烟测试 | 1 次迭代 | CI 流 | 分支变更 |
GET 端点 | 预发布 | 平均负载 | 100 请求/秒 - 3 分钟 | 在 QA/预发布期间调度 | 预发布期间每天 3 次 |
GET 端点 | 预发布 | 压力测试 | 1500 请求/秒 - 5 分钟 | 在 QA/预发布期间调度 | 预发布期间每天 3 次 |
GET 端点 | Staging | 平均负载 | 100 请求/秒 - 3 分钟 | 调度 | 每周 2 次 |
GET 端点 | 生产环境 | 50% 平均负载 | 50 请求/秒 - 3 分钟 | 在流量最小时调度 | 每周 |
规划结果分析流程
按照前面的步骤,您现在应该有了一个初步的性能测试计划。现在,让我们看看如何分析和解释性能结果。
第一步是了解您有哪些用于输出性能结果的选项。如果您正在使用 k6,有几种输出选项可供选择。您可以查看这些选项和k6 指标,以决定一个长期解决方案来分析您的测试自动化计划的结果。
以下是创建结果分析流程时需要考虑的一些问题。
如何存储您的性能结果
在 k6 中,您可以在测试结束时获取聚合结果,或者实时获取时间序列指标。这两个选项都允许您自定义输出。
我们推荐的流程是
- 选择存储后端。
- 了解它如何存储您的测试数据及其特定功能。
- 学习如何查询和可视化结果以及任何限制。
- 建立删除旧测试结果的策略,并确保保留关键性能结果以便将来进行比较,例如基线性能数据。
- 测试该解决方案并决定一个长期存储方案,以避免频繁更改此关键组件。
您将重点关注哪些关键性能指标
思考每个特定测试的目标,并确保您跟踪依赖于您测试目标的指标。
k6 提供内置指标,它们聚合了针对 SUT 的所有交互。您还可以使用标签和自定义指标来对一次交互或特定类型的结果进行分类和过滤。
考虑定义自己的性能标准及其可视化。例如,为良好、可接受、稍微令人担忧或错误的情况设置不同的颜色,以便您可以快速查看特定性能结果集是否正常。
考虑性能变化。是否有任何特定指标用于比较变化或跟踪其随时间的变化趋势?大多数测试可视化选项都关注单个测试运行的结果。考虑实现一种方法来可视化关键性能指标随时间的结果,以便您可以识别任何变化和趋势。
您将多久分析一次结果
考虑创建可以快速提供任何自动化测试最新结果概览的仪表盘和自定义通知。这些仪表盘是指示需要调查的问题的第一道防线。
此外,我们建议为重要问题设置告警。考虑优先级和非优先级级别以及后续行动。考虑这些告警设计技巧。
关联测试和可观测性数据
最后但同样重要的是,设置 SUT 的适当插桩,并了解现有系统和应用数据的监控和可观测性。
性能测试结果可以突出性能不佳的情况,例如响应缓慢。但是,它不会显示 SUT 内部发生了什么,例如缓慢的 SQL 查询或 CPU 和内存饱和。
为了弥合差距,找出一种方法将测试结果与您插桩基础设施和应用代码的方式关联起来。例如,连接或构建包含测试结果的自定义仪表盘,或使用测试中的追踪数据。
持续测试有助于检测问题和性能下降,无论是从测试结果还是系统数据。适当的可观测性将有助于找到根本原因。
示例计划
当我们最终确定规划时,我们可以根据测试运行频率、分析结果的选项以及后续行动来组织我们的测试计划。例如
部署环境。 | 测试类型 | 频率 | 告警 | 测试概览 | 行动 |
---|---|---|---|---|---|
QA | 冒烟测试 | 分支变更时 CI | CI | 修复失败的测试 | |
预发布 | 除冒烟测试外的所有性能测试 | 在 QA/预发布期间,每天 2 或 3 次 | 评估性能结果后验证发布 | ||
Staging | 基线性能测试 | 每周计划 2 次 | 仅针对关键问题 | 自定义仪表盘 | 监督测试结果 |
生产环境 | 基线性能测试 | 每周计划 | 优先级问题和非优先级问题 | 自定义仪表盘和通知 | 监督测试结果 |
生产环境 | 合成测试 | 每小时计划 | 自定义警报 | 响应警报 |
注意事项
从简单开始,然后迭代
在开始制定性能测试计划或自动化时,通常会考虑测试几十个场景。从小处着手,避免计划瘫痪。
我们建议从跨不同测试环境的几个不同测试开始。
随着时间的推移,您可以添加更多测试,您的性能测试套件将逐渐增加其测试覆盖范围。
专注于在软件发布过程中验证您的测试自动化计划和解决方案。成功的实施将为与其他团队协作以及推广持续性能测试的价值铺平道路。
测试一致性至关重要
持续性能测试的主要目标之一是评估定义可靠性和性能目标的关键指标的变化。为此,我们需要比较一段时间内不同测试运行之间这些指标的值。
比较同一测试的测试运行结果至关重要。否则,您就是在比较风马牛不相及的事物。比较相同的测试运行、相同的工作负载,在相同的环境下使用相同的测试数据运行相同的场景。
确保测试运行之间不会引入差异。如果需要更改,请重命名或创建一个新测试,然后从头开始比较测试结果。
此外,我们建议安排同一测试运行两次,且几乎连续执行。这会收集一个额外的测试运行结果以进行更好的比较,并允许我们忽略可能不可靠的测试。
确定如何停止自动化和手动测试
某些性能测试,尤其是涉及重负载测试的测试,可能会导致服务中断。无人监督地自动化执行有风险的测试可能不理想,但这并不意味着您应该避免它们。
这些测试需要受控的测试执行和对测试结果的实时分析,以便在系统变得无响应之前停止它们。
同样,当系统开始产生大量错误时,您可能希望停止测试。当系统完全过载时,继续执行测试通常不会提供更有意义的见解,而只会消耗资源。
要停止 k6 测试,请了解如何使用 abortOnFail
阈值选项 或与 k6 CLI 或 Grafana Cloud k6 集成。
通过可重复的 QA 流程补充自动化
我们在本指南开头提到了这一点:性能测试中的自动化是为了建立一个可重复且一致的测试流程。
您还应该计划手动触发并需要在执行期间监督系统的测试的频率。为了确保这些不同情况得到一致测试,请设置提醒并将它们记录为 QA 流程和发布检查清单的一部分。常见示例如下:
- 每季度运行浸泡测试。
- 在重要的季节性事件前 2 个月运行重压测试。
- 在预发布环境中对主要版本运行重负载测试。
CI/CD 中的质量门可能导致虚假的安全感
性能测试中的质量门通常定义为 通过/失败标准,用于验证发布是否满足其可靠性目标。
然而,在测试数千或数百万次交互时,设置可靠的质量门具有挑战性。测试脚本、特定环境的 SLO 以及通过/失败标准都很容易出错。
假设可靠性检查可能存在假阴性(反之亦然);确保性能测试不会错误地阻止发布。
除非您的验证流程成熟,否则不要完全依赖通过/失败结果来保证发布的可靠性。如果不确定,可以开始利用通过/失败结果来警告可能的问题以进行深入调查,并持续调整标准,直到您充满信心为止。
此外,请注意负载测试通常需要 3 到 15 分钟或更长时间;因此,将性能测试引入 CI/CD 会显著增加发布流程的时间。这也是我们建议不要在用于自动部署的流水线中运行大型测试的另一个原因。相反,应计划一天或多天在专用环境中对预发布版本进行性能测试。