

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

# 采用测试驱动型开发方法
<a name="development-best-practices"></a>

我们建议您遵循测试驱动开发 (TDD) 方法。 AWS CDK TDD 是一种软件开发方法，通过开发测试用例来指定和验证代码。简单来说，首先为每个功能创建测试用例，如果测试失败，则编写新代码以通过测试，使代码简单且无错误。

您可以先使用 TDD 编写测试用例。这可以帮助您验证具有不同设计限制的基础设施，包括为资源强制执行安全策略和遵循项目的唯一命名约定。测试 AWS CDK 应用程序的标准方法是使用 AWS CDK [断言](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html)模块和流行的测试框架，例如 [Jest fo JavaScript r and 和 Python 的 [pyt](https://docs.pytest.org/en/6.2.x/) est](https://jestjs.io/)。 TypeScript 

您可以为 AWS CDK 应用程序编写两类测试：
+ 使用**细粒度的断言**来测试生成 CloudFormation 模板的特定方面，例如 “此资源具有此值的此属性”。这些测试可以检测回归，在使用 TDD 开发新功能时也很有用（先编写测试，然后通过编写正确的实现使其通过）。细粒度断言是您最常编写的测试。
+ 使用**快照测试**根据先前存储的基线 CloudFormation 模板测试合成模板。快照测试让自由重构成为可能，因为您可以确保重构后的代码与原始代码的工作方式完全相同。如果这些更改是有意的，您可以接受新的基线，用于今后的测试。但是， AWS CDK 升级也可能导致合成模板发生变化，因此您不能仅仅依靠快照来确保实现正确。

## 单元测试
<a name="unit-test"></a>

本指南 TypeScript 专门介绍单元测试集成。要启用测试，请确保您的`package.json`文件包含以下库：`@types/jest``jest`、和 `ts-jest` in `devDependencies`。若要添加这些软件包，请运行 `cdk init lib --language=typescript` 命令。运行上述命令后，您将看到以下结构。

![\[单元测试结构\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/best-practices-cdk-typescript-iac/images/unit_test_structure.png)


以下代码是使用 Jest 库启用的`package.json`文件示例。

```
{
  ...
  "scripts": {
    "build": "npm run lint && tsc",
    "watch": "tsc -w",
    "test": "jest",
  },
  "devDependencies": {
    ...
    "@types/jest": "27.5.2",
    "jest": "27.5.1",
    "ts-jest": "27.1.5",
    ...
  }
}
```

在 **Test** 文件夹下，可以编写测试用例。以下示例显示了 AWS CodePipeline 构造的测试用例。

```
import { Stack } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import * as CodePipeline from 'aws-cdk-lib/aws-codepipeline';
import * as CodePipelineActions from 'aws-cdk-lib/aws-codepipeline-actions';
import { MyPipelineStack } from '../lib/my-pipeline-stack';
test('Pipeline Created with GitHub Source', () => {
  // ARRANGE
  const stack = new Stack();
  // ACT
  new MyPipelineStack(stack, 'MyTestStack');
  // ASSERT
  const template = Template.fromStack(stack);
  // Verify that the pipeline resource is created
  template.resourceCountIs('AWS::CodePipeline::Pipeline', 1);
  // Verify that the pipeline has the expected stages with GitHub source
  template.hasResourceProperties('AWS::CodePipeline::Pipeline', {
    Stages: [
      {
        Name: 'Source',
        Actions: [
          {
            Name: 'SourceAction',
            ActionTypeId: {
              Category: 'Source',
              Owner: 'ThirdParty',
              Provider: 'GitHub',
              Version: '1'
            },
            Configuration: {
              Owner: {
                'Fn::Join': [
                  '',
                  [
                    '{{resolve:secretsmanager:',
                    {
                      Ref: 'GitHubTokenSecret'
                    },
                    ':SecretString:owner}}'
                  ]
                ]
              },
              Repo: {
                'Fn::Join': [
                  '',
                  [
                    '{{resolve:secretsmanager:',
                    {
                      Ref: 'GitHubTokenSecret'
                    },
                    ':SecretString:repo}}'
                  ]
                ]
              },
              Branch: 'main',
              OAuthToken: {
                'Fn::Join': [
                  '',
                  [
                    '{{resolve:secretsmanager:',
                    {
                      Ref: 'GitHubTokenSecret'
                    },
                    ':SecretString:token}}'
                  ]
                ]
              }
            },
            OutputArtifacts: [
              {
                Name: 'SourceOutput'
              }
            ],
            RunOrder: 1
          }
        ]
      },
      {
        Name: 'Build',
        Actions: [
          {
            Name: 'BuildAction',
            ActionTypeId: {
              Category: 'Build',
              Owner: 'AWS',
              Provider: 'CodeBuild',
              Version: '1'
            },
            InputArtifacts: [
              {
                Name: 'SourceOutput'
              }
            ],
            OutputArtifacts: [
              {
                Name: 'BuildOutput'
              }
            ],
            RunOrder: 1
          }
        ]
      }
      // Add more stage checks as needed
    ]
  });
  // Verify that a GitHub token secret is created
  template.resourceCountIs('AWS::SecretsManager::Secret', 1);
});
);
```

若要运行测试，请在项目中运行 `npm run test` 命令。测试返回以下结果。

```
PASS  test/codepipeline-module.test.ts (5.972 s)
  ✓ Code Pipeline Created (97 ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.142 s, estimated 9 s
```

有关测试用例的更多信息，请参阅《*AWS Cloud Development Kit (AWS CDK) 开发人员指南》*中的[测试结构](https://docs.aws.amazon.com/cdk/v2/guide/testing.html)。

## 集成测试
<a name="integration-test"></a>

也可以使用`integ-tests`模块来包含 AWS CDK 构造的集成测试。集成测试应定义为 AWS CDK 应用程序。集成测试和 AWS CDK 应用程序之间应该有关 one-to-one系。如需了解更多信息，请访问 *AWS CDK API 参考*中的[integ-tests-alpha 模块](https://docs.aws.amazon.com/cdk/api/v2/docs/integ-tests-alpha-readme.html)。