この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、AWS Step Functionsステートマシンの結合テストをする方法を確認してみました。
ステートマシンの実行結果の評価がうまく行えない
AWS上に作成をしたStep Functionsステートマシンに対する動作確認(いわゆる結合テスト)を行いたい場合があります。
テスト対象は、このようなLambda関数を1つ実行するタスクがある5秒程度で終了するステートマシンとします。
そこで次のような、ステートマシンをAWS SDKで実行して実行結果が成功(SUCCEEDED
)となることを確認するテストコードを作成しました。
上手くいかないテストコード
import * as AWS from 'aws-sdk';
const sfn = new AWS.StepFunctions({
region: 'ap-northeast-1',
});
const STATE_MACHINE_ARN = process.env.STATE_MACHINE_ARN as string;
test('ステートマシンの実行が成功することを確認', async (): Promise<void> => {
//テスト対象のステートマシンを実行
const execution = await sfn
.startExecution({
stateMachineArn: STATE_MACHINE_ARN,
})
.promise();
const executionArn = execution.executionArn;
//ステートマシンの実行情報を取得
const executionDescription = await sfn
.describeExecution({ executionArn: executionArn })
.promise();
//ステートマシンの実行が成功していることを確認
expect(executionDescription.status).toBe('SUCCEEDED');
});
DescribeExecutionで確認できるステートマシンの実行ステータスの値は次のようなものがあります。このうちSUCCEEDED
となれば成功、FAILED
やTIMED_OUT
となれば失敗であることが分かります。
status
The current status of the execution.
Type: String
Valid Values: RUNNING | SUCCEEDED | FAILED | TIMED_OUT | ABORTED
Jestでテストを実行します。するとステートマシンの実行ステータスがRUNNING
(実行中)の状態でexpect()
による評価が行われてしまい、成功か失敗かの評価がうまく行えませんでした。
$ npx jest
FAIL test/stateMachine.test.ts (6.628 s)
✕ ステートマシンの実行が成功することを確認 (298 ms)
● ステートマシンの実行が成功することを確認
expect(received).toBe(expected) // Object.is equality
Expected: "SUCCEEDED"
Received: "RUNNING"
20 | .promise();
21 |
> 22 | expect(executionDescription.status).toBe('SUCCEEDED');
| ^
23 | });
24 |
at Object.<anonymous> (test/stateMachine.test.ts:22:39)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 6.684 s, estimated 8 s
Ran all test suites.
これはstartExecution
によるステートマシンの実行は非同期となるためです。
待機時間を設けることによりうまく行えた
そこでwhile
とsetTimeout
による待機時間を設けます。ステートマシンの実行ステータスがRUNNING
の間は待機をするようにします。
上手くいったテストコード
import * as AWS from 'aws-sdk';
const sfn = new AWS.StepFunctions({
region: 'ap-northeast-1',
});
const STATE_MACHINE_ARN = process.env.STATE_MACHINE_ARN as string;
test('ステートマシンの実行が成功することを確認', async (): Promise<void> => {
//テスト対象のステートマシンを実行
const execution = await sfn
.startExecution({
stateMachineArn: STATE_MACHINE_ARN,
})
.promise();
const executionArn = execution.executionArn;
//ステートマシンの実行ステータスがRUNNINGでなくなるまで待機
let executionStatus = 'RUNNING';
while (executionStatus === 'RUNNING') {
await new Promise((r) => setTimeout(r, 1000));
let res = await sfn
.describeExecution({ executionArn: executionArn })
.promise();
if (res.status !== 'RUNNING') executionStatus = res.status;
}
//ステートマシンの実行情報を取得
const executionDescription = await sfn
.describeExecution({ executionArn: executionArn })
.promise();
//ステートマシンの実行が成功していることを確認
expect(executionDescription.status).toBe('SUCCEEDED');
});
するとJestによる実行結果の評価を行えるようになりました。
$ npx jest
PASS test/stateMachine.test.ts (8.251 s)
✓ ステートマシンの実行が成功することを確認 (1769 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.299 s
Ran all test suites.
startSyncExecutionは使えないのか?
今回、テストコードからステートマシンを実行するためにstartExecution
を使用しました。このメソッドは標準ワークフローのステートマシンの実行にのみ利用可能です。今回テストを行いたかったのは標準ワークフローとなります。
StartExecution is idempotent for STANDARD workflows. For a STANDARD workflow, if StartExecution is called with the same name and input as a running execution, the call will succeed and return the same response as the original request.
もうひとつステートマシンを実行できるメソッドとしてStartSyncExecution
というものがありますが、これは標準ワークフローのステートマシンには使用できません。Expressワークフローのものに対してのみ使用できます。
Starts a Synchronous Express state machine execution. StartSyncExecution is not available for STANDARD workflows.
両者の違いとしては、標準ワークフローの実行は非同期のみとなりますが、Expressワークフローは同期での実行が可能となります。
当初、これを使用すると名前的にステートマシンの同期実行ができそうな気がして使ってみたのですが、標準ワークフローのステートマシンであったため、案の定エラーとなりました。
import * as AWS from 'aws-sdk';
const sfn = new AWS.StepFunctions({
region: 'ap-northeast-1',
});
const STATE_MACHINE_ARN = process.env.STATE_MACHINE_ARN as string;
test('ステートマシンの実行', async (): Promise<void> => {
const execution = await sfn
.startSyncExecution({
stateMachineArn: STATE_MACHINE_ARN,
})
.promise();
console.log(execution);
});
StateMachineTypeNotSupported: This operation is not supported by this type of state machine
というエラーとなっています。
$ npx jest
FAIL test/stateMachine.test.ts (6.506 s)
✕ ステートマシンの実行 (179 ms)
● ステートマシンの実行
StateMachineTypeNotSupported: This operation is not supported by this type of state machine
at Request.extractError (node_modules/aws-sdk/lib/protocol/json.js:52:27)
at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (node_modules/aws-sdk/lib/request.js:686:14)
at Request.transition (node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (node_modules/aws-sdk/lib/state_machine.js:14:12)
at node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (node_modules/aws-sdk/lib/request.js:688:12)
at Request.callListeners (node_modules/aws-sdk/lib/sequential_executor.js:116:18)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 6.555 s, estimated 11 s
Ran all test suites.
以上