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

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

はじめに

本記事ではローカル環境で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 を使用して、ローカル環境でテストを行いました。 この記事がどなたかの参考になれば幸いです。

参考