Step Functions のテストをローカル環境で行う

AWS

はじめに

本記事ではローカル環境でStep Functions のテストを行う方法として、
AWS が提供する aws-stepfunctions-local を使用する方法を記載します。

手順

テストに使用するステートマシンの定義です。(MyStateMachine.asl.json)

{
  "Comment":"This state machine is called: LambdaSQSIntegration",
  "StartAt":"LambdaState",
  "States":{
    "LambdaState":{
      "Type":"Task",
      "Resource":"arn:aws:states:::lambda:invoke",
      "Parameters":{
        "Payload.$":"$",
        "FunctionName":"HelloWorldFunction"
      },
      "Retry":[
        {
          "ErrorEquals":[
            "States.ALL"
          ],
          "IntervalSeconds":2,
          "MaxAttempts":3,
          "BackoffRate":2
        }
      ],
      "Next":"SQSState"
    },
    "SQSState":{
      "Type":"Task",
      "Resource":"arn:aws:states:::sqs:sendMessage",
      "Parameters":{
        "QueueUrl":"https://sqs.us-east-1.amazonaws.com/123456789012/myQueue",
        "MessageBody.$":"$"
      },
      "End": true
    }
  }
}

MockConfigFile.json を作成し、このファイルにテストを記述します。

{
  "StateMachines":{
    "LambdaSQSIntegration":{
      "TestCases":{
        "HappyPath":{
          "LambdaState":"MockedLambdaSuccess",
          "SQSState":"MockedSQSSuccess"
        },
        "RetryPath":{
          "LambdaState":"MockedLambdaRetry",
          "SQSState":"MockedSQSSuccess"
        },
        "HybridPath":{
          "LambdaState":"MockedLambdaSuccess"
        }
      }
    }
  },
  "MockedResponses":{
    "MockedLambdaSuccess":{
      "0":{
        "Return":{
          "StatusCode":200,
          "Payload":{
            "StatusCode":200,
            "body":"Hello from Lambda!"
          }
        }
      }
    },
    "LambdaMockedResourceNotReady":{
      "0":{
        "Throw":{
          "Error":"Lambda.ResourceNotReadyException",
          "Cause":"Lambda resource is not ready."
        }
      }
    },
    "MockedSQSSuccess":{
      "0":{
        "Return":{
          "MD5OfMessageBody":"3bcb6e8e-7h85-4375-b0bc-1a59812c6e51",
          "MessageId":"3bcb6e8e-8b51-4375-b0bc-1a59812c6e51"
        }
      }
    },
    "MockedLambdaRetry":{
      "0":{
        "Throw":{
          "Error":"Lambda.ResourceNotReadyException",
          "Cause":"Lambda resource is not ready."
        }
      },
      "1-2":{
        "Throw":{
          "Error":"Lambda.TimeoutException",
          "Cause":"Lambda timed out."
        }
      },
      "3":{
        "Return":{
          "StatusCode":200,
          "Payload":{
            "StatusCode":200,
            "body":"Hello from Lambda!"
          }
        }
      }
    }
  }
}

に従って
Step Functions Local を Docker で立ち上げます。

$ docker pull amazon/aws-stepfunctions-local
$ docker run -p 8083:8083 \
  --mount type=bind,readonly,source=$(pwd)/MockConfigFile.json,destination=/home/StepFunctionsLocal/MockConfigFile.json \
  -e SFN_MOCK_CONFIG="/home/StepFunctionsLocal/MockConfigFile.json" \
  amazon/aws-stepfunctions-local

以下コマンドで、ステートマシンを作成します。

$ stateMachineName=LambdaSQSIntegration
$ aws stepfunctions create-state-machine \
    --endpoint http://localhost:8083 \
    --definition file://$(pwd)/MyStateMachine.asl.json \
    --name $stateMachineName \
    --role-arn "arn:aws:iam::123456789012:role/service-role/LambdaSQSIntegration"
{
    "creationDate": 1659791116.288,
    "stateMachineArn": "arn:aws:states:us-east-1:123456789012:stateMachine:LambdaSQSIntegration"
}

以下コマンドで、ステートマシンを実行します。ステートマシン名の最後に”#HappyPath”をつけることで
MockConfigFile.json で定義した”HappyPath”のテストケースを実行できます。

$ executionName=executionWithHappyPathMockedServices
$ aws stepfunctions start-execution \
    --endpoint http://localhost:8083 \
    --name $executionName \
    --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:${stateMachineName}#HappyPath
{
    "startDate": 1659791128.547,
    "executionArn": "arn:aws:states:us-east-1:123456789012:execution:LambdaSQSIntegration:executionWithHappyPathMockedServices"
}

以下コマンドで、実行結果を確認します。

$ aws stepfunctions get-execution-history \
  --endpoint http://localhost:8083 \
  --execution-arn arn:aws:states:us-east-1:123456789012:execution:${stateMachineName}:${executionName}

以下は出力の一部です。内容を確認すると、output から”HappyPath”のテストケースが実行されていることがわかります。

{
    "events": [
        ...
        {
            "timestamp": 1659792667.443,
            "type": "TaskStateEntered",
            "id": 2,
            "stateEnteredEventDetails": {
                "input": "{}",
                "inputDetails": {
                    "truncated": false
                },
                "name": "LambdaState"
            },
            "previousEventId": 0
        },
        ...
        {
            "timestamp": 1659792667.642,
            "type": "TaskSucceeded",
            "id": 5,
            "taskSucceededEventDetails": {
                "resourceType": "lambda",
                "output": "{\"StatusCode\":200,\"Payload\":{\"StatusCode\":200,\"body\":\"Hello from Lambda!\"}}",
                "outputDetails": {
                    "truncated": false
                },
                "resource": "invoke"
            },
            "previousEventId": 4
        },
        ...
        {
            "timestamp": 1659792667.65,
            "taskScheduledEventDetails": {
                "resourceType": "sqs",
                "region": "us-east-1",
                "resource": "sendMessage",
                "parameters": "{\"QueueUrl\":\"https://sqs.us-east-1.amazonaws.com/123456789012/myQueue\",\"MessageBody\":{\"StatusCode\":200,\"Payload\":{\"StatusCode\":200,\"body\":\"Hello from Lambda!\"}}}"
            },
            "type": "TaskScheduled",
            "id": 8,
            "previousEventId": 7
        },
        ...
        {
            "timestamp": 1659792667.652,
            "stateExitedEventDetails": {
                "output": "{\"MD5OfMessageBody\":\"3bcb6e8e-7h85-4375-b0bc-1a59812c6e51\",\"MessageId\":\"3bcb6e8e-8b51-4375-b0bc-1a59812c6e51\"}",
                "outputDetails": {
                    "truncated": false
                },
                "name": "SQSState"
            },
            "type": "TaskStateExited",
            "id": 11,
            "previousEventId": 10
        },
        ...
    ]
}

おわりに

本記事では aws-stepfunctions-local を使用して、ローカル環境でテストを行いました。
この記事がどなたかの参考になれば幸いです。

参考

コメント