AWS CDK のスナップショットテストを Vitest で実装してみた

2023.12.12

こんにちは、CX 事業本部 Delivery 部の若槻です。

Vite を活用したテスティングフレームワークである Vitest ですが、このたび 2 年間のプレリリース版を経てついに v1.0.0 がリリースされました。

この Vitest は JavaScript テスティングフレームワークとして多くのマッチャーや API が Jest と互換性があり、また実行速度も比較的高速化できるという特徴があります。

今回は、この Vitest のリリース版を使用して、AWS CDK のスナップショットテストの実装を試してみました。

やってみた

CDK プロジェクトの初回作成

cdk init コマンドで CDK プロジェクトの初回作成を行います。

mkdir cdk_app_sample && cd cdk_app_sample
cdk init --language typescript

Jest のアンインストール

CDK はデフォルトで Jest がインストールされるため、Jest をアンインストールします。

npm uninstall @types/jest jest ts-jest

Vitest のインストール

Vitest をインストールします。この時、Vite のインストールは不要です。Vitest の依存関係としてはインストールされます。

npm install vitest --save-dev

インストールされたバージョンは v1.0.4 です。

$ npm ls vitest     
cdk_app_sample@0.1.0 $HOME/projects/cm-rwakatsuki/cdk_app_sample
└── vitest@1.0.4

CDK スタックのソースコードの作成

CDK スタックのソースコードです。まずは何も作成しないスタックとします。

lib/cdk_app_sample-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

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

スナップショットファイルの初回作成

CDK スナップショットのテストコードです。vitest のメソッドをインポートしている以外は Jest のスナップショットテストとコードの内容は同じです。

test/cdk_app_sample.test.ts

import { test, expect } from 'vitest'
import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';

import * as CdkAppSample from '../lib/cdk_app_sample-stack';

test('CDK Sample App Stack', () => {
  const app = new cdk.App();

  const stack = new CdkAppSample.CdkAppSampleStack(app, 'CdkAppSampleStack');

  const template = Template.fromStack(stack);

  expect(template).toMatchSnapshot();
});

Vitest でテストを実行します。

$ npx vitest ./test --run

 RUN  v1.0.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_app_sample

 ✓ test/cdk_app_sample.test.ts (1)
   ✓ CDK Sample App Stack

  Snapshots  1 obsolete
             ↳ test/cdk_app_sample.test.ts
               · SQS Queue Created 1

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  00:39:35
   Duration  384ms (transform 55ms, setup 0ms, collect 172ms, tests 45ms, environment 0ms, prepare 51ms)

すると __snapshots__ 配下に次のような初回のスナップショットファイルが作成されます。

test/__snapshots__/cdk_app_sample.test.ts.snap

// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`CDK Sample App Stack 1`] = `
{
  "Parameters": {
    "BootstrapVersion": {
      "Default": "/cdk-bootstrap/hnb659fds/version",
      "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]",
      "Type": "AWS::SSM::Parameter::Value<String>",
    },
  },
  "Rules": {
    "CheckBootstrapVersion": {
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": [
              {
                "Fn::Contains": [
                  [
                    "1",
                    "2",
                    "3",
                    "4",
                    "5",
                  ],
                  {
                    "Ref": "BootstrapVersion",
                  },
                ],
              },
            ],
          },
          "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.",
        },
      ],
    },
  },
}
`;

CDK スタックのソースコード修正

CDK スタックのソースコードを修正します。CfnOutput を追加します。

lib/cdk_app_sample-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

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

    new cdk.CfnOutput(this, 'HelloWorld', {
      value: 'Hello World!'
    });
  }
}

再度スナップショットテストを実行すると、テスト実行が失敗します。

$ npx vitest ./test --run

 RUN  v1.0.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_app_sample

 ❯ test/cdk_app_sample.test.ts (1)
   × CDK Sample App Stack

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  test/cdk_app_sample.test.ts > CDK Sample App Stack
Error: Snapshot `CDK Sample App Stack 1` mismatched

- Expected
+ Received

@@ -1,6 +1,11 @@
  {
+   "Outputs": {
+     "HelloWorld": {
+       "Value": "Hello World!",
+     },
+   },
    "Parameters": {
      "BootstrapVersion": {
        "Default": "/cdk-bootstrap/hnb659fds/version",
        "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]",
        "Type": "AWS::SSM::Parameter::Value<String>",

 ❯ test/cdk_app_sample.test.ts:14:20
     12|   const template = Template.fromStack(stack);
     13| 
     14|   expect(template).toMatchSnapshot();
       |                    ^
     15| });
     16| 

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

  Snapshots  1 failed
 Test Files  1 failed (1)
      Tests  1 failed (1)
   Start at  00:51:29
   Duration  746ms (transform 305ms, setup 0ms, collect 449ms, tests 56ms, environment 0ms, prepare 71ms)

スナップショットの更新

スタックのコードの更新に合わせて、テストのスナップショットも更新します。更新するためには -u オプションを付けて Vitest を実行するだけです。

$ npx vitest ./test --run -u

 RUN  v1.0.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_app_sample

 ✓ test/cdk_app_sample.test.ts (1)
   ✓ CDK Sample App Stack

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  00:52:32
   Duration  348ms (transform 26ms, setup 0ms, collect 148ms, tests 45ms, environment 0ms, prepare 40ms)

git diff コマンドを実行すると、スナップショットファイルの差分が確認できます。

$ git diff        
diff --git a/test/__snapshots__/cdk_app_sample.test.ts.snap b/test/__snapshots__/cdk_app_sample.test.ts.snap
index f87f30f..7f08f8f 100644
--- a/test/__snapshots__/cdk_app_sample.test.ts.snap
+++ b/test/__snapshots__/cdk_app_sample.test.ts.snap
@@ -2,6 +2,11 @@
 
 exports[`CDK Sample App Stack 1`] = `
 {
+  "Outputs": {
+    "HelloWorld": {
+      "Value": "Hello World!",
+    },
+  },
   "Parameters": {
     "BootstrapVersion": {
       "Default": "/cdk-bootstrap/hnb659fds/version",

再度 -u オプションを付けずにテストを実行すると、今度はテストが成功するようになりました。

$ npx vitest ./test --run

 RUN  v1.0.4 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_app_sample

 ✓ test/cdk_app_sample.test.ts (1)
   ✓ CDK Sample App Stack

 Test Files  1 passed (1)
      Tests  1 passed (1)
   Start at  01:32:49
   Duration  672ms (transform 260ms, setup 0ms, collect 402ms, tests 56ms, environment 0ms, prepare 58ms)

おわりに

AWS CDK のスナップショットテストを Vitest で実装してみました。

CDK ではデフォルトで Jest が使用されますが、Vitest へ入れ替えてスナップショットテストへの利用を簡単に行うことができました。このたびのプロダクト版のリリースを機に、皆さんも試してみてはいかがでしょうか。

以上