Amazon Web Services ブログ
あらゆる言語でのCDKアプリケーションのテスト
AWS Cloud Development Kit (AWS CDK)は、使い慣れたプログラミング言語でクラウドアプリケーションのリソースを定義するためのオープンソースソフトウェア開発フレームワークです。AWS CDKはインフラストラクチャをプログラミング言語で定義できるため、アプリケーションのコードと同様に、インフラストラクチャのコードに対しても自動化されたユニットテストを記述することができます。テストは効果的なDevOpsの実践のために重要な要素であり、インフラストラクチャのコードをテストすることで、AWSクラウドで期待通りのリソースを確実に作成することができ、リグレッションが発生するのを防ぐことができるなどのメリットがあります。
今日、私はAWS CDK用のassertions モジュールを発表できることを嬉しく思います。これはCloudFormationテンプレートを中心に、CDKアプリケーションに対してユニットテストを書くのに役立つように設計されたAPIのセットです。
すべての言語をサポート
以前のAWS Blogの記事では、JavaScriptとTypeScriptでのみ利用可能なassert
モジュールを使ってテストを書く方法を説明しました。assert
モジュールと同様に、新しいCDK assertions
モジュールは、CDKアプリによって生成(synthesize
)されたCloudFormationテンプレートを正確に検証するためのAPIセットを提供します。さらに、新しいassertions
モジュールは、CDKがサポートするすべての言語に対応しています。
新しいassertions
モジュールはCDKがサポートするすべての言語をサポートしていますが、この記事のスニペットはPythonで書かれています。これらのサンプルの完全なソースコードはGitHubで公開されており、TypeScript、Java、およびPythonで書かれた同等のコードが含まれています。
きめ細かな(Fine-grained) アサーション
assertions
モジュールは、テンプレートのある部分が与えられたオブジェクトにマッチすることをアサートしたり、テンプレートのある部分を検索するためのツールをいくつか提供しています。これらのツールを使って、与えられたタイプとプロパティを持つリソースが存在することをアサートしたり、特定の出力が存在することをアサートしたり、テンプレートが与えられた数のリソースを持っていることをアサートしたりすることができます。
下記のコードのように、AWS Step Functions のステートマシンと AWS Lambda 関数を作成するスタック(ProcessorStack
) があるとします。Lambda関数は Amazon SNS のトピックをサブスクライブしており、メッセージ受けるとステートマシンを起動します。
このスタックをきめ細かなアサーションでテストするにはどうすればよいでしょうか。
まず ProcessorStack
スタックを作り、CloudFormationのテンプレートを生成します。生成したテンプレートに対してアサーションを行うことができます。
さらに ProcessorStack
は、クロススタックリファレンスで他のスタックのリソース (SNSトピックの配列)を参照しますが、このスタックもテストコードの中で作成することができます
これで、Lambda関数とサブスクリプションが作成されたことをアサートできます。
has_resource_properties()
メソッドを使用すると、 テンプレートが指定された型のリソースを指定されたプロパティで持っていることをアサートすることができます。この例では、期待通りのリソースがそれぞれ存在し、テストで定義した特定のプロパティが設定されていることをアサートします。またテンプレートクラスには他にも多くのメソッドがあり、CloudFormationテンプレートのResources
、Outputs
、Mappings
の検証に使用できます。
マッチャー(Matcher)
前述の例のアサーションを見ると、テストされるプロパティはすべてリテラル値として定義されていることがわかります。assertions
モジュールのメソッドは、テンプレートアサーション中に部分的または特別なパターンマッチングを定義することができるマッチャーを使用することもできます。assertions
モジュールにはいくつかのマッチャーが組み込まれており、その全リストは assertions API reference に記載されています。たとえば、Match.object_like()
メソッドは、期待する値 (has_resource_properties()
に渡されるプロパティ) がターゲット値 (生成されたリソース上のプロパティ) のサブセットであることをチェックします。Match.object_like()
マッチャーは、CDKライブラリのアップデートによって追加のプロパティが導入された場合にテストが失敗するのを防ぐためによく使われます。
次の例では、ユニットテストでさまざまなマッチャーを使用する方法を示します。Match.object_equals()
マッチャーは、期待される値がサブセットではなくターゲットの値と完全に等しいかどうかをチェックします。一方、Match.any_value()
マッチャーは、ターゲットの値が何であってもアサーションが通るようにします。これらの2つのマッチャーを組み合わせて使用することで、ステートマシンのIAM roleに対して完全にアサーションを行うことができます。
次の例では、Step Functionsステートマシンのアサーションがユニットテストに含まれています。ステートマシンは、Amazon State Languages (JSONベース)で書かれた文字列で定義されます。これはステートマシンを表現するためには優れていますが、助けとなるツールがなければテストするのは困難です。幸いなことに、assertions
モジュールには Match.serialized_json()
というマッチャーが用意されており、対象となる文字列を JSON でデシリアライズし、期待される値と照合します。Match.serialized_json()
マッチャーの中にマッチャーを入れ子にすることもできます。
キャプチャー(Capture)
assertions
モジュールの Capture
API を使用すると、assertions
モジュールがマッチングする際の値を取得し、後でそれらの値に対して独自のアサーションを実行することができます。Capture
オブジェクトを作成し、他のマッチャーと同じようにアサーションで使用し、 関連する as_x()
メソッド (as_string()
や as_object()
など) でその値を取得します。
このスニペットでは、Capture
とMatch.serialized_json()
マッチャーの組み合わせを使用して、ステートマシンの開始状態の名前が “Start” で始まること、および開始状態がマシンの状態リスト内に実際に存在することをアサートしています。
スナップショットテスト
CDKのアプリケーションをテストするもう一つの方法として、スナップショットテストがあります。スナップショットテストは、最初の実行時にオブジェクトのスナップショットを取得します。このスナップショットはバージョンコントロールにコミットされ、その後テストが実行されるたびに、オブジェクトとスナップショットが比較されます。スナップショットがオブジェクトと一致した場合、アサーションはパスします。スナップショットが一致しない場合には、アサーションは失敗します。
スナップショットテストは、標準的なユニットテストとは異なり、リグレッションを検出するメカニズムではありません。AWS CDKアプリの生成時に生成されるCloudFormationテンプレートは、CDKアプリケーションのコードとCDKフレームワークの両方から影響を受けます。場合によっては、CDKフレームワークのバージョンがアップグレードされると、生成されるテンプレートが変わることがあります。これは通常、新しいベストプラクティスがCDKに組み込まれたときに起こります。このような理由から、スナップショットテストは、CDKスタックに何か変化があった場合に警告を発する仕組みとして使用するのが最適です。スナップショットテストを行うことで、これらの変更をすばやく確認することができます。
CDKのコードをリファクタリングする場合も、スナップショットテストが有効です。リファクタリング中に何かが変わってしまうことは避けたいものですが、スナップショットテストはそれが起きたときに明確に教えてくれます。その他のほとんどのユースケースでは、きめ細かなアサーションがより良いツールとなります。
assertions
モジュールでスナップショットテストを行うには、まずスタックからCloudFormationテンプレートに生成し、テンプレート全体をオブジェクト (JavaではMap、Pythonではdict) に変換し、テストフレームワークのスナップショットテスト機能を使って、テンプレートがそのスナップショットと一致することをアサートします。
コンストラクトのテスト
assertions
モジュールを使用すると、スタックと同様にコンストラクトをテストすることができます。その場合はテストの中でコンストラクトを格納するスタックを新しく作成します。
例えば、DeadLetterQueue
というコンストラクトがあるとします (以前 Testing infrastructure with the AWS Cloud Development Kit の記事で使用したものです)。
これはこのようにテストできます。
まとめ
テストは、コードが期待通りに動作することを確認し、変更を行う際のデグレや予期せぬ変更を防ぐために重要です。新しいAWS CDKのassertions
モジュールは、特にassert
モジュールが利用できない言語で開発している場合に、インフラストラクチャをコードとしてテストするための新しい強力な方法を提供します。assertions
モジュールの詳細については、API referenceを参照してください。aws-cdk の GitHub リポジトリでは、バグレポート、機能リクエスト、プルリクエストを受け付けています。
この記事はTesting CDK Applications in Any Languageを翻訳したものです。翻訳はPrototype Engineerの工藤が担当しました。