View a markdown version of this page

测试无服务器应用程序的最佳实践 - AWS 规范性指导

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

测试无服务器应用程序的最佳实践

以下各节概述了在测试无服务器应用程序时实现有效覆盖的最佳实践。

优先考虑在云端进行测试

对于精心设计的应用程序,您可以使用各种测试技术来满足一系列要求和条件。但是,根据当前的工具,我们建议您尽可能专注于云端测试。尽管在云端进行测试可能会造成开发人员延迟,增加成本,有时还需要在额外 DevOps 控制方面进行投资,但这种技术提供了最可靠、最准确和最完整的测试覆盖范围。

您应该可以访问用于执行测试的隔离环境。理想情况下,每个开发人员都应有一个专门的资源, AWS 账户 以避免在多个使用相同代码的开发人员尝试在具有相同名称的资源上部署或调用 API 调用时可能出现的任何资源命名问题。应为环境配置警报和控件,以避免产生不必要的支出。例如,您可以限制可创建的资源的类型、层级或资源大小,并在估计成本超出给定阈值时设置电子邮件警报。

如果您必须 AWS 账户 与其他开发者共享单个资源,则自动测试流程应为每个开发者命名独一无二的资源。例如,导致 AWS SAM CLI sam depl oy 或 sam sync 命令的更新脚本或 TOML 配置文件可以自动指定包含本地开发者用户名的堆栈名称。

云端测试对于测试的所有阶段都很有价值,包括单元测试、集成测试和 end-to-end测试。

必要时使用 Mock

Mock 框架是编写快速单元测试的重要工具。当测试涵盖复杂的内部业务逻辑(例如数学或财务计算或模拟)时,此框架尤其有用。寻找具有大量测试使用案例或输入变体的单元测试,其输入不会改变调用其他云服务的模式或内容。为这些场景创建 Mock 测试可以缩短开发人员的迭代时间。

包含在单元测试中的、使用 Mock 测试的代码也应包含在云端测试中。这是必要的,因为模拟仍在开发人员的笔记本电脑或构建计算机上运行,并且环境的配置可能与云中的配置不同。例如,在使用某些输入参数运行时,您的代码可能包含占用更多内存或花费更多时间的 Lambda 配置为分配的 AWS Lambda 函数。或者,您的代码可能包含未以相同方式(或根本没有)配置的环境变量,这些差异可能会导致代码行为不同或失败。

不要使用模拟云服务来验证这些服务集成的实施是否正确。尽管在测试其他功能时模拟云服务可能是可以接受的,但您应该在云中测试云服务调用,以验证配置和功能实现是否正确。

模拟可以为单元测试增加价值,尤其是在你经常测试大量案例时。集成测试的这一好处会降低,因为实现必要模拟的工作量会随着连接点数量的增加而增加。 End-to-end测试不应使用模拟,因为这些测试通常处理的状态和复杂逻辑无法用模拟框架轻松模拟。

了解仿真测试的权衡

对于特定用例,仿真器可能是一种实用的选择。例如,互联网访问受限、不一致或速度缓慢的开发团队可能会发现,在迁移到云环境之前,仿真测试是最可靠的代码迭代方式。

对于大多数其他情况,请选择性地使用模拟器。当你严重依赖仿真器时,在仿真供应商发布更新以提供功能对等之前,可能很难将新的 AWS 服务功能整合到测试中。仿真器还需要前期和持续的投资,以便跨开发系统和构建机器进行设置和配置。此外,许多云服务没有可用的仿真器;选择仿真优先策略可能会阻止使用这些服务,或者生成的代码和配置没有针对实际服务行为进行充分测试。

如果您使用仿真测试,请尽可能多地使用云测试对其进行补充,以验证是否有正确的云配置,并测试与只能在模拟环境中进行模拟或模拟的服务的交互。

仿真测试可以为单元测试提供快速反馈,并且还可能支持一些集成和 end-to-end测试,具体取决于仿真软件的功能和行为奇偶性。

通过自然界限进行范围测试

随着无服务器应用程序跨越更多架构组件的增长,子系统周围会出现自然界限,尤其是在遵循单一用途函数和事件驱动的解耦等最佳实践时。这些边界是有效的测试边缘,您可以在其中验证组件之间的合约。

确定架构边界

在应用设计中寻找自然的接缝:

  • 服务之间,例如将出版商与消费者关联起来的亚马逊 EventBridge 规则

  • 在 API 边缘,例如前置 Lambda 函数的 Amazon API Gateway 终端节点

  • 围绕工作流程,例如 AWS Step Functions 协调多项服务

  • 在存储层,例如触发下游处理的 Amazon DynamoDB 流

将 Lambda 代码与业务逻辑分开

将 Lambda 代码与核心业务逻辑隔离开来,从而简化测试。您的 Lambda 处理程序应充当 AWS 运行时和应用程序逻辑之间的精简适配器。它应该提取并验证事件数据,然后委托给没有 Lambda 依赖关系的可测试函数。这使您的业务逻辑可移植、更易于推理,并且无需模拟 Lambda 对象或设置复杂环境即可直接进行测试。

把界限当作合约对待

在边界进行测试,而不是通过边界进行测试。无需整个下游系统即可验证跨越边缘的内容。这些相同的边界也可以用作生产中的可观察性挂钩。可以对您测试的架构接缝进行检测,以便使用 Amazon CloudWatch 日志、 AWS X-Ray 跟踪和 EventBridge事件进行监控。

为异步工作流程使用测试工具

无服务器应用程序通常依赖异步模式,在这种模式下,事件触发处理,消息流经队列,工作流跨多个服务而没有即时响应。你不能简单地调用函数并检查返回值。结果可能会稍后出现在数据库、日志流或其他服务中。

测试工具是测试您与应用程序一起部署的基础架构,以观察和验证这种异步行为。测试线束通常包括:

  • 订阅应用程序生成的相同事件的事件监听器

  • 可以捕获测试结果的存储机制(例如 DynamoDB 表或 Amazon S3 存储桶)

  • 测试代码中用于等待预期结果出现的轮询逻辑

您的测试代码启动一个事件,等待工作流程完成,然后查询测试工具以验证是否实现了预期结果。

以下是最佳实践:

  • 明确 SLAs 异步操作 — 确定工作流程应花费多长时间,并在测试中将其用作轮询超时

  • 使用唯一标识符进行测试隔离 — 每次测试运行生成唯一的文件名 IDs、消息或关联标记,以防止测试之间的干扰

  • 在@@ 应用程序旁边部署测试基础架构 — 在 infrastructure-as-code模板中加入测试工具资源,以便它们随着应用程序的发展保持同步

  • 在@@ 测试运行后清理测试数据 — 这样可以防止在云环境中积累测试工件

测试工具对于验证多项服务工作流程的集成测试、验证完整用户旅程的 end-to-end测试以及服务通过 Amazon SNS、Amazon EventBridge SQS 或 Amazon Kinesis 进行通信的事件驱动架构最有价值。

整理云环境以隔离开发人员

在云端进行测试需要相互隔离的环境。当开发者共享单个 AWS 账户帐户(例如团队开发帐户)时,可以考虑为每个开发者或功能分支创建一个单独的应用程序堆栈。这样可以隔离资源,防止命名冲突,并避免在测试期间出现配额争用或邻居噪音问题。

使用 AWS Systems Manager Parameter Store 或类似工具来管理特定于堆栈的配置,例如 API 端点和队列名称。为了提高成本效益,请在开发人员堆栈之间共享昂贵的资源,例如亚马逊关系数据库服务 (Amazon RDS) 集群,同时保持每个堆栈的轻量级无服务器资源(例如 Lambda 函数、API Gateway 阶段和 DynamoDB 表)隔离。

在受监管的行业中,企业安全策略可能会限制开发人员访问云环境,这使得在本地开发工作流程中运行云测试变得困难。在这些情况下,仿真测试可以填补本地模拟测试和全面云验证之间的空白,但只要访问允许,就应辅之以云测试。

加速反馈循环

当您在云端进行测试时,请使用工具和技术来加速开发反馈循环。例如,使用AWS SAM 加速和 AWS CDK 监视模式来缩短将代码修改推送到云环境所需的时间。 GitHub Serverless 测试样本存储库中的示例探讨了其中一些技术。

我们还建议您在开发期间尽早从本地计算机创建和测试云资源,而不仅仅是在签入源代码管理之后。这种做法有助于在开发解决方案时更快地进行探索和实验。此外,从开发计算机自动执行部署的能力可以帮助您更快地发现云配置问题,并减少浪费在对源控制进行更新和批准修改上的工作量。