Amazon Web Services ブログ

AWS Step Functions の強化されたローカルテストでワークフロー開発を加速する

2025 年 11 月 19 日は、AWS のテスト API である TestState API を使用した AWS Step Functions のローカルテスト機能強化について皆さんにお知らせしたいと思います。

これらの機能強化は TestState API 経由で利用できるため、任意のテストフレームワークを使用して開発マシン上でワークフロー定義をローカルに検証し、エラー処理パターン、データ変換、サービスのモック統合をテストする自動テストスイートを構築できます。今回のリリースによってローカルユニットテストのための API ベースのアプローチが導入されたので、Amazon Web Services (AWS) にデプロイしなくても包括的なテスト機能にプログラム的にアクセスできるようになります。

強化された TestState API には、次の 3 つの主要機能が導入されています。

  • モックサポート – ダウンストリームのサービスを呼び出すことなくステート出力とエラーをモックできるため、ステートマシンロジックの真のユニットテストが可能になります。TestState は、STRICT (すべての必須フィールドを検証するデフォルトモード)、PRESENT (フィールドのタイプと名前を検証)、NONE (検証なし) の 3 つの検証モードを使用してモックレスポンスを AWS API モデルに照らして検証することで、忠実度の高いテストを実現します。
  • すべてのステートタイプのサポート – Map ステート (インラインおよび分散)、Parallel ステート、アクティビティベースの Task ステート、.sync サービス統合パターン、.waitForTaskToken サービス統合パターンなどの高度なステートを含めたすべてのステートタイプをテストできるようになりました。これは、ステートの遷移、エラー処理、データ変換などの制御フローロジックを検証するために、ワークフロー定義全体で TestState API を使用し、ユニットテストを作成できることを意味します。
  • 個々のステートのテスト – 新しい StateName パラメータを使用して、完全なステートマシン定義内で特定のステートをテストします。完全なステートマシン定義を 1 度提供するだけで、各ステートを名前で個別にテストできます。実行コンテキストを制御して、特定のリトライ試行、Map のイテレーション順番、エラーシナリオをテストできます。

強化された TestState の使用を開始する
強化された TestState の新機能を順を追って見ていきましょう。

シナリオ 1: 正常な結果をモックする

1 つ目の機能はモックサポートです。この機能を使用して、実際の AWS サービスや外部の HTTP リクエストさえも呼び出すことなくワークフローロジックをテストできます。ユニットテストをすばやく行うためにサービスレスポンスをモックしたり、統合テストのために実際の AWS サービスを使ってテストしたりできます。モックレスポンスを使用するときに AWS Identity and Access Management (IAM) 許可は必要ありません。

以下は、正常な AWS Lambda 関数レスポンスをモックする方法です。

aws stepfunctions test-state --region us-east-1 \
--definition '{
  "Type": "Task",
  "Resource": "arn:aws:states:::lambda:invoke",
  "Parameters": {"FunctionName": "process-order"},
  "End": true
}' \
--mock '{"result":"{\"orderId\":\"12345\",\"status\":\"processed\"}"}' \
--inspection-level DEBUG

このコマンドは、実際に関数を呼び出すことなく Lambda 呼び出しステートをテストします。TestState は、モックレスポンスを Lambda サービス API モデルに照らして検証して、テストデータがサービスから実際に返されるものと一致することを確認します。

レスポンスには、実行が正常に行われたことと、詳細な検査データが表示されます (DEBUG 検査レベルの使用時)。

{
    "output": "{\"orderId\":\"12345\",\"status\":\"processed\"}",
    "inspectionData": {
        "input": "{}",
        "afterInputPath": "{}",
        "afterParameters": "{\"FunctionName\":\"process-order\"}",
        "result": "{\"orderId\":\"12345\",\"status\":\"processed\"}",
        "afterResultSelector": "{\"orderId\":\"12345\",\"status\":\"processed\"}",
        "afterResultPath": "{\"orderId\":\"12345\",\"status\":\"processed\"}"
    },
    "status": "SUCCEEDED"
}

モックレスポンスを指定すると、TestState がそのレスポンスを AWS サービスの API モデルに照らして検証し、モックされたデータが期待されるスキーマに従っているのを確認するため、実際の AWS サービスコールを必要とせずに忠実度の高いテストを維持できます。

シナリオ 2: エラー状態をモックする
エラー状態をモックしてエラー処理ロジックをテストすることも可能です。

aws stepfunctions test-state --region us-east-1 \
--definition '{
  "Type": "Task",
  "Resource": "arn:aws:states:::lambda:invoke",
  "Parameters": {"FunctionName": "process-order"},
  "End": true
}' \
--mock '{"errorOutput":{"error":"Lambda.ServiceException","cause":"Function failed"}}' \
--inspection-level DEBUG

このコマンドは Lambda サービス例外をシミュレートするので、AWS 環境内でエラーを実際に発生させることなく、ステートマシンがどのように失敗を処理するのかを検証できます。

レスポンスには、失敗した実行とエラーの詳細が表示されます。

{
    "error": "Lambda.ServiceException",
    "cause": "Function failed",
    "inspectionData": {
        "input": "{}",
        "afterInputPath": "{}",
        "afterParameters": "{\"FunctionName\":\"process-order\"}"
    },
    "status": "FAILED"
}

シナリオ 3: Map ステートをテストする
2 番目の機能は、これまでサポートされていなかったステートタイプのサポートを追加します。以下は、Distributed Map ステートをテストする方法です。

aws stepfunctions test-state --region us-east-1 \
--definition '{
  "Type": "Map",
  "ItemProcessor": {
    "ProcessorConfig": {"Mode": "DISTRIBUTED", "ExecutionType": "STANDARD"},
    "StartAt": "ProcessItem",
    "States": {
      "ProcessItem": {
        "Type": "Task",
        "Resource": "arn:aws:states:::lambda:invoke",
        "Parameters": {"FunctionName": "process-item"},
        "End": true
      }
    }
  },
  "End": true
}' \
--input '[{"itemId":1},{"itemId":2}]' \
--mock '{"result":"[{\"itemId\":1,\"status\":\"processed\"},{\"itemId\":2,\"status\":\"processed\"}]"}' \
--inspection-level DEBUG

モック結果は、複数アイテムの処理からの完全な出力を表しています。この場合、モック配列が期待される Map ステートの出力形式と一致する必要があります。

レスポンスは、配列入力が正常に処理されたことを示しています。

{
    "output": "[{\"itemId\":1,\"status\":\"processed\"},{\"itemId\":2,\"status\":\"processed\"}]",
    "inspectionData": {
        "input": "[{\"itemId\":1},{\"itemId\":2}]",
        "afterInputPath": "[{\"itemId\":1},{\"itemId\":2}]",
        "afterResultSelector": "[{\"itemId\":1,\"status\":\"processed\"},{\"itemId\":2,\"status\":\"processed\"}]",
        "afterResultPath": "[{\"itemId\":1,\"status\":\"processed\"},{\"itemId\":2,\"status\":\"processed\"}]"
    },
    "status": "SUCCEEDED"
}

シナリオ 4: Parallel ステートをテストする
複数のブランチを同時に実行する Parallel ステートも同様にテストできます。

aws stepfunctions test-state --region us-east-1 \
--definition '{
  "Type": "Parallel",
  "Branches": [
    {"StartAt": "Branch1", "States": {"Branch1": {"Type": "Pass", "End": true}}},
    {"StartAt": "Branch2", "States": {"Branch2": {"Type": "Pass", "End": true}}}
  ],
  "End": true
}' \
--mock '{"result":"[{\"branch1\":\"data1\"},{\"branch2\":\"data2\"}]"}' \
--inspection-level DEBUG

モック結果は、ブランチごとに 1 つの要素を持つ配列である必要があります。TestState を使用することにより、モックデータ構造が実際の Parallel ステート実行で生成されるものと一致することがわかります。

レスポンスには、並列実行の結果が表示されます。

{
    "output": "[{\"branch1\":\"data1\"},{\"branch2\":\"data2\"}]",
    "inspectionData": {
        "input": "{}",
        "afterResultSelector": "[{\"branch1\":\"data1\"},{\"branch2\":\"data2\"}]",
        "afterResultPath": "[{\"branch1\":\"data1\"},{\"branch2\":\"data2\"}]"
    },
    "status": "SUCCEEDED"
}

シナリオ 5: 完全なワークフロー内で個々のステートをテストする
StateName パラメータを使用して、完全なステートマシン定義内で特定のステートをテストできます。以下は、単一のステートをテストする例ですが、完全なワークフロー定義を提供し、テストするステートを指定するのが一般的です。

aws stepfunctions test-state --region us-east-1 \
--definition '{
  "Type": "Task",
  "Resource": "arn:aws:states:::lambda:invoke",
  "Parameters": {"FunctionName": "validate-order"},
  "End": true
}' \
--input '{"orderId":"12345","amount":99.99}' \
--mock '{"result":"{\"orderId\":\"12345\",\"validated\":true}"}' \
--inspection-level DEBUG

このコマンドは、特定の入力データを使用して Lambda 呼び出しステートをテストするもので、TestState がその入力をどのように処理し、ステート実行を通じて変換するのかを示します。

レスポンスには、入力の処理と検証の詳細が表示されます。

{
    "output": "{\"orderId\":\"12345\",\"validated\":true}",
    "inspectionData": {
        "input": "{\"orderId\":\"12345\",\"amount\":99.99}",
        "afterInputPath": "{\"orderId\":\"12345\",\"amount\":99.99}",
        "afterParameters": "{\"FunctionName\":\"validate-order\"}",
        "result": "{\"orderId\":\"12345\",\"validated\":true}",
        "afterResultSelector": "{\"orderId\":\"12345\",\"validated\":true}",
        "afterResultPath": "{\"orderId\":\"12345\",\"validated\":true}"
    },
    "status": "SUCCEEDED"
}

これらの機能強化は、使い慣れたローカル開発エクスペリエンスを Step Functions ワークフローに取り入れるため、変更を AWS アカウントにデプロイする前にそれらに関するフィードバックを即座に得ることができます。自動テストスイートを作成し、クラウド実行と同じ信頼性レベルですべての Step Functions 特徴量を検証できるため、デプロイ時にワークフローが期待どおりに動作するという自信が得られます。

知っておきたいこと
留意点は以下のとおりです。

  • 可用性 – 強化された TestState 機能は、Step Functions がサポートされているすべての AWS リージョンでご利用いただけます。
  • 料金 – TestState API コールは AWS Step Functions に含まれており、追加の料金はかかりません。
  • フレームワーク互換性 – TestState は HTTP リクエストを行うことができるすべてのテストフレームワーク (Jest、pytest、JUnit など) で動作します。デプロイ前に、継続的インテグレーションと継続的デリバリー (CI/CD) パイプラインでワークフローを自動的に検証するテストスイートを作成できます。
  • 特徴量サポート – 強化された TestState は、Distributed Map ステート、Parallel ステート、エラー処理、JSONATA 式など、すべての Step Functions 特徴量をサポートします。
  • ドキュメント – さまざまな構成に対するオプションの詳細については TestState ドキュメント、更新されたリクエストおよびレスポンスモデルについては API リファレンスを参照してください。

TestState を開発ワークフローに統合して、強化されたローカルテストを今すぐ始めましょう。

ハッピービルディング!
– Donnie

原文はこちらです。