使用 AWS 对来自 GitHub 的 Node.js 应用程序运行单元测试 CodeBuild - AWS Prescriptive Guidance

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

使用 AWS 对来自 GitHub 的 Node.js 应用程序运行单元测试 CodeBuild

Thomas Scott 和 Jean-Baptiste Guillois,亚马逊 Web S

摘要

此模式为 Node.js 游戏 API 提供了示例源代码和关键单元测试组件。它还包括使用 AWS 从 GitHub 存储库运行这些单元测试的说明 CodeBuild,这是持续集成和持续交付 (CI/CD) 工作流程的一部分。

单元测试是一个软件开发过程,在这个过程中,对应用程序的不同部分(称为单元)进行单独和独立的测试,以确保其正确运行。测试验证代码的质量并确认其功能是否符合预期。其他开发人员也可以通过查阅测试轻松熟悉您的代码库。单元测试可缩短未来的重构时间,帮助工程师更快地掌握代码库,并让他们对预期行为充满信心。

单元测试涉及测试单个函数,包括 AWS Lambda 函数。要创建单元测试,您需要一个测试框架和一种验证测试(断言)的方法。此模式中的代码示例使用 Mocha 测试框架和 Chai 断言库。 

有关单元测试和测试组件示例的更多信息,请参阅其他信息部分。

先决条件和限制

  • 具有正确 CodeBuild 权限的活跃 AWS 账户

  • GitHub 账户(参见注册说明

  • Git(请参阅安装说明

  • 用于进行更改并将代码推送到的代码编辑器 GitHub

架构

此模式实施下图中所示的架构。

AWS 云架构,用于使用 CodeBuild 和 GitHub 存储库运行单元测试

工具

工具

  • Git 是一个版本控制系统,你可以用它来开发代码。

  • AWS CodeBuild 是一项完全托管的持续集成服务,可编译源代码、运行测试并生成可随时部署的软件包。使用 CodeBuild,您无需预置、管理和扩展自己的构建服务器。 CodeBuild 持续扩展并同时处理多个构建,因此您的构建不会排队等待。您可以使用预先打包的构建环境快速开始,也可以创建使用您自己的构建工具的自定义构建环境。使用 CodeBuild,按分钟计费所使用的计算资源。

代码

此模式的源代码可在 GitHub示例游戏单元测试应用程序存储库中找到。您可以根据此示例(选项 1)创建自己的 GitHub 存储库,也可以直接使用示例存储库(选项 2)来创建此模式。按照下一节中每个选项的说明操作。选项的选择因用例而定。

操作说明

Task描述所需技能

根据示例项目创建自己的 GitHub 存储库。

  1. 登录到 GitHub。

  2. 创建新存储库。有关说明,请参阅GitHub 文档

  3. 克隆示例存储库并将其推送到您账户中的新存储库中。

应用程序开发人员、AWS 管理员、AWS DevOps

创建新 CodeBuild 项目。

  1. 登录 AWS 管理控制台,然后在 https://console.aws.amazon.com/codesuite/codebuild /h CodeBuild ome 中打开控制台。

  2. 选择 Create build project(创建构建项目)

  3. 在 “项目配置” 部分,在 “项目名称” 中键入 aws-tests-sample-node-js

  4. 在 “来源” 部分中,对于源提供商,选择GitHub

  5. 对于 “存储库”,在我的 GitHub 账户中选择 “存储库”,然后将 URL 粘贴到新创建的 GitHub 存储库中。

  6. 主要源 Webhook 事件中, 选择每次将代码更改推送到此存储库时都会重新生成 

  7. 对于事件类型,选择推送。 

  8. 环境部分,选择托管映像、Amazon Linux 和最新映像。

  9. 所有其他选项保留默认设置,然后选择创建构建项目

应用程序开发人员、AWS 管理员、AWS DevOps

开始构建。

审核页面上,选择开始构建以运行构建。

应用程序开发人员、AWS 管理员、AWS DevOps
Task描述所需技能

创建新的 CodeBuild 构建项目。

  1. 登录 AWS 管理控制台,然后在 https://console.aws.amazon.com/codesuite/codebuild /h CodeBuild ome 中打开控制台。

  2. 选择 Create build project(创建构建项目)

  3. 在 “项目配置” 部分,在 “项目名称” 中键入 aws-tests-sample-node-js

  4. 在 “来源” 部分中,对于源提供商,选择GitHub

  5. 对于 “存储库”,选择 “公共存储库”,然后粘贴 URL: https://github.com/aws-samples/node-js-tests-sample

  6. 环境部分,选择托管映像、Amazon Linux 和最新映像。

  7. 所有其他选项保留默认设置,然后选择创建构建项目

应用程序开发人员、AWS 管理员、AWS DevOps

开始构建。

审核页面上,选择开始构建以运行构建。

应用程序开发人员、AWS 管理员、AWS DevOps
Task描述所需技能

查看测试结果。

在 CodeBuild 控制台中,查看 CodeBuild 作业的单元测试结果。这些结果应与其他信息部分中显示的结果相符。

这些结果验证了 GitHub 存储库与的集成 CodeBuild。 

应用程序开发人员、AWS 管理员、AWS DevOps

应用 Webhook。

现在,您可以应用 Webhook,这样无论何时将代码变更推送到存储库的主分支,都可以自动启动构建。有关说明,请参阅CodeBuild 文档

应用程序开发人员、AWS 管理员、AWS DevOps

相关资源

其他信息

单元测试结果

成功构建项目后,您应该会在 CodeBuild 控制台中看到以下测试结果。 

单元测试的预期结果

单元测试组件示例

本节介绍单元测试中使用的四种类型的测试组件:断言、间谍、存根和模拟。它包括每个组件的简要说明和代码示例。 

断言

断言用于验证预期结果。这是一个重要的测试组件,因为它可以验证给定函数的预期响应。以下示例断言验证了初始化新游戏时返回的 ID 是否介于 0 和 1000 之间。

const { expect } = require('chai'); const { Game } = require('../src/index'); describe('Game Function Group', () => { it('Check that the Game ID is between 0 and 1000', function() { const game = new Game(); expect(game.id).is.above(0).but.below(1000) }); });

间谍

间谍用于观察函数运行时发生的情况。例如,您可能希望验证函数的调用是否正确。以下示例显示了在游戏类对象上调用启动和停止方法。

const { expect } = require('chai'); const { spy } = require('sinon'); const { Game } = require('../src/index'); describe('Game Function Group', () => { it('should verify that the correct function is called', () => { const spyStart = spy(Game.prototype, "start"); const spyStop = spy(Game.prototype, "stop"); const game = new Game(); game.start(); game.stop(); expect(spyStart.called).to.be.true expect(spyStop.called).to.be.true }); });

存根

存根用于覆盖函数的默认响应。当函数发出外部请求时,这特别有用,因为您想避免从单元测试中发出外部请求。(外部请求更适合集成测试,集成测试可以对不同组件之间的请求进行物理测试。) 在以下示例中,存根强制从 getId 函数返回一个 ID。

const { expect } = require('chai'); const {.stub } = require('sinon'); const { Game } = require('../src/index'); describe('Game Function Group', () => { it('Check that the Game ID is between 0 and 1000', function() { let generateIdStub = stub(Game.prototype, 'getId').returns(999999); const game = new Game(); expect(game.getId).is.equal(999999); generateIdStub.restore(); }); });

模拟

模拟是一种虚假的方法,具有用于测试不同场景的预编程行为。模拟可以被视为存根的扩展形式,可以同时执行多个任务。在以下示例中,使用模拟来验证三个场景:

  • 调用函数 

  • 使用参数调用函数

  • 函数返回整数 9

const { expect } = require('chai'); const {.mock } = require('sinon'); const { Game } = require('../src/index'); describe('Game Function Group', () => { it('Check that the Game ID is between 0 and 1000', function() { let mock = mock(Game.prototype).expects('getId').withArgs().returns(9); const game = new Game(); const id = get.getId(); mock.verify(); expect(id).is.equal(9); }); });