更进一步
如果不想为测试 SQS 队列而烦恼并降低基础设施部分的风险,我建议像下图一样扩展测试。 它往往会成为一个集成测试,你会在反馈中失去一些精确性,但可以保持你的基础设施代码直截了当。
另一方面,在测试其他一些无服务器组件时,你可能需要添加更多基础设施才能执行断言。 例如,对于 SNS 和 EventBridge,无法轮询主题或总线,因此我们需要一种方法来断言消息/事件已被正确接收。 为此,我们可以添加一个测试 SQS 队列:
我的观点:
●在测试队列中将 MessageRetentionPeriod 设置为最小值(60 秒),以便自动清除超过一分钟的消息(以防测试未正确清理)。
●鼓励每位开发人员拥有一个 AWS 账户。 这样做可以降低单个帐户超出免费套餐的风险,并降低测试期间发生冲突的风险(每个人都使用相同的 SQS 队列……)。 如果不可能,请确保为每个开发人员部署一个堆栈并定义命名约定(例如“昵称-mystack”)。
选项 #3:
集成测试在之前的所有选项中,我们都缺少两个基本方面:
●函数的触发器(与上游服务集成):API 调用、DynamoDB 流、SQS 轮询。
●与下游服务交互的 Lambda 函数权限(执行角色)。
集成测试允许涵盖这一点:不在本地调用 Lambda 函数,而是使用上游服务触发已部署的 Lambda 函数,然后该函数将与实际服务交互。 查看示例,它看起来像这样:
我们仍然可以使用喜欢的编程语言和工具来编写这些测试,这使得编写它们非常方便。 利用 AWS SDK 来执行操作和断言,或者在 API 的情况下简单地请求端点。
对这个选项进行评级,在准确性 (4) 上获得了在精度上失去的东西 (3):我们测试了真实的服务,完全集成并部署在 AWS 上,这提供了非常好的准确性,但是当测试失败时,它就变成了更难确定确切原因(这是否是因为Lambda 函数?)。 还有较慢的测试 (2):调用 rest api,在 DynamoDB 表中插入项目,……无疑需要更多时间并增加故障排除时间。 谈到成本,实施起来稍微复杂一些,排除故障也更耗时,这导致了 3。
我的观点 :
●没什么特别的,我真的不推荐这些测试。 它们提供了更好的准确性,但仍不是最佳选择(参见选项 #4)。
选项 #4:端到端测试
将通过端到端测试到达最后一个选项。 顾名思义,其目的是验证整个系统是否已良好集成并在云端端到端运行。 至于集成测试,将使用 JUnit/Jest/… 和 AWS SDK 编写测试用例。 然而这一次,没有拆分工作,而是测试整个“功能”。在示例中,验证了在使用一些数据调用 API 时,最终在 RDS 数据库中获得了预期的输出:
这些测试的主要好处是它们的准确性:可以按照与生产环境相同的方式部署所有内容,无需测试队列或专用基础设施。 如果测试在测试环境中通过,那么它在以后的生产环境中应该也能正常工作。 请注意,只有当使用基础设施即代码和框架(如 SAM、CDK 或无服务器)并在不同环境中部署相同的基础设施时,情况才会如此。 但是今天到底是谁手动部署了这个基础设施呢?
另一方面,这些测试的大问题是测试失败时缺乏准确性。 必须对链的每个组件进行故障排除,以找出问题出在哪里。 AWS X-Ray 和 CloudWatch ServiceLens 可以提供帮助,但并非所有服务都与 X-Ray 集成。 还可以利用其他工具:用于查询日志并搜索错误或特定事件的 CloudWatch Logs Insights,或者提供无服务器应用程序指标的 CloudWatch Lambda Insights。
这种测试的另一个缺点是它们通常很难设置。 不是因为基础设施(使用 IaC),而是因为数据。 需要获得一个干净的数据集(在我们的示例中的 RDS 中),可能会从生产环境中检索它,这意味着匿名化数据、删除 PII……测试后清理数据也可能很复杂。 对于此类测试尤其如此,因为它们通常在共享环境(集成、UAT、preprod 等)中执行。
同样,如果可以获得一个可以执行这些测试的干净(非共享)环境,那会更好,这样就可以每次都使用全新的干净数据集填充数据库。 基础设施即代码就在这里,你使用它!
查看雷达,我们有以下图表:
●如前所述,准确性是最佳的 (5),在真实条件下进行测试(前提是拥有正确的数据集)。
●精度真的很低 (1) 并且更难排除故障。
●我们正在失去速度 (1),因为需要部署所有东西,执行测试的时间也很长,更难排除故障也意味着要花更多的时间在上面。
●时间就是金钱! 这就是我将利率降为 1 的主要原因。
我的观点:
●显然,测试金字塔和蜂窝也同意这一点,不要在这些测试上投入太多。 使用它们来验证基础架构的不同“路径”。 在示例中,主要有一条路径,即一次测试。 例如,如果在某个地方有一个 EventBridge,它具有将事件发送到不同目标的不同规则,我们将为每个规则添加一个测试。 如果有一个字符队列,我们也会想检查“错误路径”。 Step Functions 更复杂:是否必须验证所有路径和条件呢? 你必须验证状态机的所有分支,以确保它配置良好并与它调用的所有服务集成。
●这里的目标是仅验证之前无法验证的内容:每个服务和权限之间的集成。 你可以用另一种测试用例来验证某些内容。
●不要连续运行这些测试。与你希望每天运行数百次的单独和社交测试相反,这些测试运行的频率较低,并且通常不是从笔记本电脑而是从 CI/CD 流水线上运行的。 记住它们会很慢,不要等待它们运行。
结论
我们并不真正关心测试的形状,无论是三角形、蜂窝还是其他任何形状。 下面这是一朵花:
但是,我们必须关心的是为工作使用适当的测试。 我总结一下:
●对 Lambda 函数的业务逻辑使用单独测试。 尽可能尝试从处理程序中提取此业务,以避免模拟,尤其是 AWS 模拟。 六边形架构是一个加号,但不是强制性的。 这样就可以在不部署到云的情况下测试业务(如果有的话)。 如果拥有的唯一“业务”是协调其他 AWS 服务,那么 Step Functions 可能更合适,但这是另一个话题。
●不要依赖模拟 Lambda 的社交测试。
●支持社交测试:在本地调用处理程序方法,而不模拟对 AWS 服务的外部调用。 根据介绍中列出的四个标准,这些测试获得了 3.75/5 的最佳分数。
●不要依赖集成测试,更喜欢提供更高准确性的端到端测试,但不要过度投资。 只需验证基础架构路径(服务之间的集成:事件和消息、配置、权限)。