Serverless 架构中的测试策略与方法
在 Serverless 架构的开发与部署过程中,测试是确保系统稳定性和性能的关键环节。本文将深入探讨 Serverless 架构中不同类型的测试,包括测试内容的确定、各类测试的特点和实施方法,以及同步和异步测试的区别。
确定测试内容
在部署代码时,决定测试内容是一个挑战。开发过程中的自动化测试通常由代码仓库的更新触发,进而启动带有内置自动化测试的部署管道。
-
新部署
:对于新部署,直接运行所有测试即可。
-
现有应用变更部署
:当对现有应用进行变更部署时,管道难以确定哪些部分发生了变化以及应该测试哪些内容。具体情况如下:
-
基础设施变更
:需要对模板运行基础设施即代码(IaC)测试,并在部署后进行集成测试。
-
代码更新
:仅需运行单元测试。如果代码更改影响了任何集成组件,则还需要运行集成测试。如果该组件是工作流的一部分,可能需要运行端到端测试以确保工作流按预期运行。
然而,配置这些测试较为复杂且容易出错。为了安全起见,每次部署后运行所有测试是一种选择,但对于大型应用来说,这会耗费大量时间,影响生产力。对于大型团队开发的应用,集成和端到端测试可能会因为其他团队成员未完成相关组件而失败,导致部署被拒绝,降低生产力。
为了解决这些问题,可以采用多仓库方法和个人开发环境:
-
多仓库方法
:每个仓库有自己的部署管道,测试仅覆盖该部署及其集成。一个单独的仓库包含不同团队成员组件之间的集成测试和整个工作流的端到端测试,这些测试在各个仓库通过自身测试后较少运行。
-
个人开发环境
:对于 Serverless 架构,个人开发环境相对容易且成本效益高,因为只根据实际使用情况计费。部署管道应配置为将每个仓库分支部署到其自己的独特环境中,使团队成员能够独立运行测试,不受其他开发者的干扰和依赖。
测试类型
测试通常遵循“安排 - 执行 - 评估”(Arrange - Act - Assert)的通用结构,这种方法适用于单元测试、集成测试和端到端测试。
-
安排(Arrange)
:准备执行测试所需的一切,如部署云服务、创建本地模拟事件、准备要测试的代码和输入数据。
-
执行(Act)
:执行代码和测试。
-
评估(Assess)
:确认结果是否符合预期,可能是成功结果或正确处理预期错误。
以下是不同类型测试的详细介绍:
1.
单元测试
-
特点
:大多数开发者熟悉单元测试,有许多支持单元测试的库、工具和资源,可减少学习曲线和开发工作量。单元测试速度快、可完全自动化,通常在本地运行,无需部署任何内容即可获得即时反馈。
-
示例代码
:
import lambda_src_path.index as handler
def test_lambda():
"""
Validate add method
"""
# Arrange
num_1 = 1
num_2 = 2
# Act
ans = handler.add(num_1, num_2)
# Assert
assert ans == 5
- **应用场景**:单元测试还可用于在部署前验证基础设施即代码模板,但不能保证模板的有效性,只是降低常见问题的发生概率。为了实现全面的代码覆盖,需要编写大量测试,通常会使开发工作量翻倍。在 Serverless 应用中,由于单元测试的价值相对降低,可能难以证明这种额外工作量的合理性。此外,当本地测试无法访问外部云服务时,可以使用模拟或伪造服务响应来解决问题,但需要定期维护。
-
集成测试
- 测试架构 :创建一个测试服务与应用内的组件进行交互。例如,测试服务调用 Lambda 微服务,微服务将记录存储在集成的 DynamoDB 服务中,DynamoDB 的响应记录到 CloudWatch 并决定微服务的响应。测试服务通过评估微服务的响应来确定测试是否通过。
- 重要性 :集成测试对于 Serverless 架构至关重要,因为该架构很大程度上依赖于与各种云服务的集成。除了测试错误,还可以测试性能、延迟和瓶颈,以帮助确定优化工作的优先级。
- 自动化与成本 :集成测试虽然较难自动化,但可以通过开发支持微服务和配置额外服务(如 X - Ray 或 Synthetics)来实现。建议建立一个共享测试框架,提高生产力。虽然可以使用模拟在本地运行集成测试,但通常价值有限,一般需要在部署的云基础设施上运行,以确保测试使用实时服务的真实响应和错误消息。集成测试需要部署基础设施和代码更改,并且会受到服务运行时、网络速度、触发延迟等因素的影响,增加执行时间和成本。
-
端到端测试
- 测试方式 :端到端测试是对整个工作流的高级评估,更接近实际用户行为,只需一次测试即可覆盖整个工作流。例如,向 API Gateway 端点发送请求,然后等待响应,不监控工作流中的组件,仅关注是否收到预期响应。
- 局限性与解决方案 :工作流中任何组件出现错误通常会导致 API Gateway 返回相同的标准错误消息,无法明确问题所在。因此,端到端测试必须与组件测试或主动日志记录相结合,以便更轻松地查找和解决问题。可以选择运行单个端到端测试获取工作流的总运行时间,或实施各个组件之间的集成测试以详细分解时间,但后者工作量较大。
-
用户模拟
- 工具与应用 :端到端测试可以借助工具(如 Appium、Selenium 和 Katalon)在浏览器或移动应用中模拟用户行为,如点击按钮、填写表单等,然后评估结果页面的内容来完成测试。
- 注意事项 :测试整个工作流需要部署整个系统及其依赖项,与集成测试一样,运行测试会产生费用。为了获得准确结果,建议测试环境尽可能复制生产环境,包括完整数据集或至少逼真的模拟数据。对于复杂工作流,需要多个测试变体以覆盖所有可能路径和边缘情况。
-
契约测试
- 背景与需求 :当开发者更新组件时,需要测试以确保更改不会破坏任何集成的消费者。传统的集成和端到端测试需要不同开发者之间大量的协调,因为所有依赖组件都必须可用并更新以处理新更改。
- 测试原理 :契约定义了组件预期请求和响应的结构,包括参数、传输协议和主体。定义好的契约发送到代理进行验证和存储,组件通过代理进行消息传递,代理验证请求并返回预期响应。
- 工具与流程 :可以使用开源工具 Pact 进行契约测试,它可以提供代理和数据库,并提供与代理交互和运行测试的代码库,支持多种编程语言。企业版 Pactflow 提供了高级功能。服务开发者可以从代理获取所有消费者发布的契约,测试新更新是否会破坏现有集成,测试结果发布回代理。消费者开发者也可以在部署更改前检查与提供者的集成是否中断。
-
不同测试类型的比较
| 测试类型 | 测试对象 | 测试环境 | 特点 |
| — | — | — | — |
| 单元测试 | 微服务内的代码片段和函数 | 本地 | 使用模拟避免云部署,测试速度快 |
| 契约测试 | 通过请求和响应消息间接验证微服务 | 可灵活选择 | 不直接测试代码,避免组件依赖 |
| 集成测试 | 组件之间的集成 | 部署的基础设施 | 需要所有组件可用,测试实际集成情况 |
异步测试
Serverless 架构常使用异步请求,同步测试难以评估异步事件。例如,在 S3 存储桶添加新文件触发 Lambda 函数的场景中,同步端到端测试上传文件后,S3 的即时响应仅表明上传成功,无法确定 Lambda 是否被触发或处理图像。为了评估这些异步事件,需要额外的测试,如验证处理后的图像、检查调用日志或模拟触发获取 Lambda 响应。
其他具有挑战性的异步测试场景包括:
-
SQS 服务
:SQS 有“至少一次”的传递保证,需要测试意外重复消息。
-
死信队列(DLQ)
:测试多次失败、DLQ 故障转移事件以及后续操作。
-
批处理作业
:测试批处理的部分处理情况,如成功项是否重复、失败项是否丢失。
-
Lambda 并发限制
:测试 Lambda 并发限制较为困难,需要降低限制。
-
Step Functions
:由于其复杂的路径和数据处理能力,需要多个测试来验证工作流的各种可能结果。
在异步测试中,单元测试通常帮助不大,需要结合端到端测试和集成测试。例如,使用端到端测试启动上传过程,使用集成测试验证文件是否存储在结果存储桶中。
综上所述,Serverless 架构的测试需要综合考虑不同类型的测试,根据具体情况选择合适的测试方法和策略,以确保系统的稳定性和性能。同时,要注意测试的复杂性、成本和时间开销,通过合理的配置和工具使用,提高测试效率和生产力。
Serverless 架构中的测试策略与方法(续)
契约测试在 Serverless 架构中的应用调整
虽然契约测试最初并非为 Serverless 架构设计,而是用于基于容器的微服务,但经过适当调整,它仍能为 Serverless 架构带来价值。
在 Serverless 架构中,微服务之间通常会有一个托管的解耦器(如 SQS 或 SNS),对这种托管服务进行严格的契约测试价值不大。因为 Serverless 架构尽量减少自定义代码,优先使用托管云服务,而对于无法更改的托管服务编写契约测试意义有限。
为了在 Serverless 架构中有效应用契约测试,需要进行以下调整:
1.
考虑解耦器
:微服务之间存在托管解耦器,测试时应关注微服务之间的数据交换,而不是解耦器本身。例如,形成一个契约,规定组件 B 要求请求中包含 ID、名称和价格字段,底层消息传递技术可以是 SQS、EventBridge 等。契约需要考虑技术对消息结构的任何更改,但不测试具体技术。
2.
选择测试组件
:可以决定在测试中包含哪些组件以及哪些组件进行模拟。避免对无法更改的托管服务进行不必要的测试,专注于微服务之间的交互和数据交换。
以下是一个 mermaid 流程图,展示了 Serverless 架构中契约测试的调整流程:
graph LR
A[确定微服务交互] --> B[定义契约]
B --> C[考虑解耦器影响]
C --> D[选择测试组件]
D --> E[执行契约测试]
E --> F{测试通过?}
F -- 是 --> G[部署更新]
F -- 否 --> H[修复问题]
H --> B
不同类型测试的详细比较
为了更清晰地了解各种测试类型的特点和适用场景,我们进一步详细比较它们:
| 测试类型 | 测试对象 | 测试环境 | 优点 | 缺点 | 适用场景 |
| — | — | — | — | — | — |
| 单元测试 | 微服务内的代码片段和函数 | 本地 | 速度快、可自动化、即时反馈、减少云部署 | 难以实现全面代码覆盖、对外部服务依赖处理复杂 | 开发初期验证代码逻辑、快速迭代 |
| 集成测试 | 组件之间的集成 | 部署的云基础设施 | 验证组件间交互、测试真实响应和错误 | 部署和执行时间长、成本高、难以自动化 | 验证架构集成、性能和瓶颈测试 |
| 端到端测试 | 整个工作流 | 接近生产环境 | 模拟用户行为、覆盖整个流程 | 难以定位问题、无法详细分解时间 | 验证工作流整体功能、用户体验测试 |
| 契约测试 | 通过请求和响应消息间接验证微服务 | 可灵活选择 | 避免组件依赖、减少开发者协调 | 不适用于托管服务、需要额外配置代理 | 组件更新时验证集成兼容性 |
| 用户模拟 | 整个工作流中的用户交互 | 模拟生产环境 | 真实模拟用户行为、评估用户体验 | 部署成本高、需要复制生产环境 | 测试用户界面和交互流程 |
异步测试的挑战与解决方案
异步测试在 Serverless 架构中面临诸多挑战,以下是一些常见挑战及相应的解决方案:
1.
SQS 服务的“至少一次”交付保证
-
挑战
:SQS 有“至少一次”的交付保证,可能会出现意外重复消息,但无法按需强制 SQS 产生重复消息。
-
解决方案
:编写测试用例,模拟可能导致重复消息的情况,如网络故障或服务重启。检查系统是否能够正确处理重复消息,避免数据不一致或错误处理。
2.
死信队列(DLQ)测试
-
挑战
:需要测试多次失败、DLQ 故障转移事件以及后续操作,如警报。
-
解决方案
:创建测试场景,故意触发多次失败,确保消息被正确转移到 DLQ。验证 DLQ 故障转移机制是否正常工作,并检查后续警报是否按预期发送。
3.
批处理作业测试
-
挑战
:测试批处理的部分处理情况,如成功项是否重复、失败项是否丢失。
-
解决方案
:设计测试用例,模拟部分处理失败的情况,检查系统如何处理成功和失败的项。确保成功项不会重复处理,失败项不会丢失,并且可以进行后续处理。
4.
Lambda 并发限制测试
-
挑战
:测试 Lambda 并发限制较为困难,需要降低限制。
-
解决方案
:在测试环境中适当降低 Lambda 并发限制,模拟高并发场景。检查系统是否能够正确处理并发请求,避免出现资源耗尽或性能下降的问题。
5.
Step Functions 测试
-
挑战
:由于其复杂的路径和数据处理能力,需要多个测试来验证工作流的各种可能结果。
-
解决方案
:根据 Step Functions 的不同路径和条件,设计多个测试用例。确保每个可能的结果都得到验证,包括顺序和并行处理、数据拆分和合并等情况。
以下是一个异步测试的操作步骤列表:
1.
确定异步事件
:识别 Serverless 架构中的异步事件,如 S3 触发 Lambda、SQS 消息处理等。
2.
设计测试用例
:根据异步事件的特点和可能的场景,设计相应的测试用例,包括正常情况、异常情况和边界情况。
3.
模拟异步事件
:使用工具或代码模拟异步事件的触发,如上传文件到 S3、发送消息到 SQS 等。
4.
执行测试
:启动测试,观察系统的响应和处理过程。
5.
验证结果
:根据测试用例的预期结果,验证系统的输出是否符合要求。可以检查数据存储、日志记录、消息通知等。
6.
处理异常情况
:如果测试过程中出现异常情况,记录错误信息并进行分析。修复问题后重新执行测试。
总结
Serverless 架构的测试是一个复杂而重要的过程,需要综合运用多种测试类型,根据不同的场景和需求选择合适的测试方法。单元测试适用于快速验证代码逻辑,集成测试用于验证组件间的交互,端到端测试和用户模拟可以模拟真实用户行为,契约测试有助于解决组件更新时的集成兼容性问题,而异步测试则需要针对特定的异步事件和挑战进行专门设计。
在实施测试时,要注意测试的复杂性、成本和时间开销。可以采用多仓库方法和个人开发环境来提高测试效率,减少不同团队成员之间的干扰和依赖。同时,建立共享测试框架,使用合适的工具(如 Pact)进行契约测试,能够进一步提升测试的生产力和准确性。
通过合理的测试策略和方法,可以确保 Serverless 架构的稳定性、性能和可靠性,为用户提供高质量的服务。
超级会员免费看

被折叠的 条评论
为什么被折叠?



