1
0

【AWS CDKテスト入門】Assertionテストのテストパターン ~Templateメソッド編~

Posted at

この記事について

前回こちらの記事でSnapshotテストとAssertionテストの使い方について考えてみました。
今回からは、AWS CDK(Cloud Development Kit)のAssertionテストについて、具体的な書き方について深掘りしていきます。本記事では第一弾として、Templateクラスのメソッドに焦点を当て、その使い方について紹介します。

対象読者

本記事は、以下のような読者を対象としています。

  • インフラストラクチャのコードにテストを導入したいと考えている方
  • CDKアプリケーションにテストを導入することを検討している方
  • Assertionテストの書き方について知りたい方

この記事では触れないこと

  • AWS CDKの基礎的な使い方
  • 特定のAWSリソースについての深い技術的解説

動作環境

この記事の内容は以下の環境で動作確認を行っています。

  • Node.js 20.15.0
  • TypeScript 5.5.2
  • AWS CDK v2(2.150.0)

テスト対象となるStack

lib/cdk_test_study-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

export class CdkTestStudyStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const Bucket = new s3.Bucket(this, 'CdkTestStudyBucket1', {
      bucketName: 'hogehoge',
      enforceSSL: true,
      objectLockEnabled: true,
      versioned: true,
    });

    new s3.Bucket(this, 'CdkTestStudyBucket2', {
      objectLockEnabled: true,
      removalPolicy: cdk.RemovalPolicy.RETAIN
    });
  
    // S3のBucketNameをoutput
    new cdk.CfnOutput(this, 'S3BucketName', {
      value: Bucket.bucketName,
    });
  }
}

リソースのプロパティの内容をチェックしたいとき

hasResourceProperties

指定されたプロパティを持つリソースが存在することを確認することができます。

該当のプロパティを持つリソースが1つでもあればテストは成功します。作成されるAWSリソース全てが特定のプロパティを満たしているかを確認したい場合は、次に紹介するallResourcesPropertiesを使いましょう。

test("ObjectLockを有効にしているS3バケットが存在すること", () => {
  template.hasResourceProperties("AWS::S3::Bucket", {
    BucketName: "hogehoge"
  });
});

allResourcesProperties

指定したリソース全てが特定のプロパティを持つことを確認することができます。
作成したS3全てがオブジェクトロック有効となっているかを確認したい場合などに有効です。

test("全てのS3バケットでObjectLockが有効になっていること", () => {
  template.allResourcesProperties("AWS::S3::Bucket", {
    ObjectLockEnabled: true,
  });
});

リソースのプロパティ以外の要素をチェックしたいとき

hasResource

指定したタイプのリソースが存在することを確認することができます。
hasResourcePropertiesのとき同様、全てのAWSリソースに対してテストしたい場合はallResourcesを使いましょう。

test("削除ポリシーがRetainでS3バケットが存在すること", () => {
  template.hasResource("AWS::S3::Bucket", {
    DeletionPolicy: "Retain",
  });
});

allResources

指定したタイプのリソースが存在することを確認することができます。
hasResourcePropertiesのとき同様、全てのAWSリソースに対してテストしたい場合はallResourcesを使いましょう。

test("全てのS3バケットの削除ポリシーがRetainであること", () => {
  template.allResources("AWS::S3::Bucket", {
    DeletionPolicy: "Retain",
  });
});

リソースの個数をチェックしたいとき

resourceCountIs

リソースが、指定された数だけ存在することを確認することができます。

test("作成されるS3バケットが2つであること", () => {
  template.resourceCountIs("AWS::S3::Bucket", 2);
});

resourcePropertiesCountIs

指定したプロパティを持つリソースが、指定された数だけ存在することを確認することができます。

test("ObjectLockを有効にしているS3バケットが2つ存在すること", () => {
  template.resourcePropertiesCountIs("AWS::S3::Bucket", {
    ObjectLockEnabled: true,
  }, 2);
});

Templateから特定のリソースに関する情報を取得したいとき

CloudFormationTempalteから特定のリソースに関する情報を取得したい場合は、以下のfind〇〇メソッドを使用します。例としてfindResourcesを紹介していますが、Templateのセクションに合わせて、find〇〇メソッドを同じように使うことができます。

findResources

TemplateのResourcesセクションから、条件に該当する特定のリソースタイプに関する部分を抽出することができます。
例えば、S3 Bucketに関する部分を出力したい場合は以下のように記述します。

const s3 = template.findResources("AWS::S3::Bucket", {});
{
  CdkTestStudyBucket13535E829: {
    Type: 'AWS::S3::Bucket',
    Properties: {
      BucketName: 'hogehoge',
      ObjectLockEnabled: true,
      VersioningConfiguration: [Object]
    },
    UpdateReplacePolicy: 'Retain',
    DeletionPolicy: 'Retain'
  },
  CdkTestStudyBucket2D584685D: {
    Type: 'AWS::S3::Bucket',
    Properties: { ObjectLockEnabled: true },
    UpdateReplacePolicy: 'Retain',
    DeletionPolicy: 'Retain'
  }
}

リソースタイプのみ指定する場合は該当リソースに関する部分が全て抽出されるため、Propertiesを指定することでリソースを限定することもできます。

const s3 = template.findResources("AWS::S3::Bucket", {
  Properties: {
    BucketName: "hogehoge",
  },
});
{
  CdkTestStudyBucket13535E829: {
    Type: 'AWS::S3::Bucket',
    Properties: {
      BucketName: 'hogehoge',
      ObjectLockEnabled: true,
      VersioningConfiguration: [Object]
    },
    UpdateReplacePolicy: 'Retain',
    DeletionPolicy: 'Retain'
  }
}

Templateのセクションに特定の値が含まれているか確認したいとき

CloudFormationTemplateから各セクションに特定の値が含まれているか確認したい場合は、以下のhas〇〇メソッドを使用します。例としてhasOutputsを紹介していますが、Templateのセクションに合わせて、has〇〇メソッドを同じように使うことができます。

hasOutputs

TemplateのOutputsセクションに、条件に該当する記述が含まれている確認することができます。例えば、S3 BucketをOutputsに含めているか確認する場合は以下のように記述します。

test("S3のBucketNameをOutputしていること", () => {
  const s3 = template.findResources("AWS::S3::Bucket", {
    Properties: {
      BucketName: "hogehoge",
    },
  });

  template.hasOutput('S3BucketName', {
    Value: { 
      Ref: Object.keys(s3)[0]
    }
  });
});

まとめ

本記事ではアサーションテストで使用するメソッドのうち、Templateクラスのメソッドについて紹介しました。
hasResourcePropertiesresourceCountIsなどのメソッドは特に利用頻度も高く、Assertionテストを作成する上で知っておくべきメソッドだと感じました。
次回はより詳細なAssertionテストを作成するために欠かせない、Matchクラスのメソッドについて深掘りしたいと思います。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0