Using TestState API to test a state - AWS Step Functions

Using TestState API to test a state

The TestState API accepts the definition of a single state and executes it. You can test a state without creating a state machine or updating an existing state machine.

Using the TestState API, you can test the following:

To test a state, you can also use the Step Functions console, AWS Command Line Interface (AWS CLI), or the SDK.

The TestState API assumes an IAM role which must contain the required IAM permissions for the resources your state accesses. For information about the permissions a state might need, see IAM permissions for using TestState API.

Considerations about using the TestState API

Using the TestState API, you can test only one state at a time. The states that you can test include the following:

While using the TestState API, keep in mind the following considerations.

Using inspection levels in TestState API

To test a state using the TestState API, you provide the definition of that state. The test then returns an output. For each state, you can specify the amount of detail you want to view in the test results. These details provide additional information about the state you're testing. For example, if you've used any input and output data processing filters, such as InputPath or ResultPath in a state, you can view the intermediate and final data processing results.

Step Functions provides the following levels to specify the details you want to view:

All these levels also return the status and nextState fields. status indicates the status of the state execution. For example, SUCCEEDED, FAILED, RETRIABLE, and CAUGHT_ERROR. nextState indicates the name of the next state to transition to. If you haven't defined a next state in your definition, this field returns an empty value.

For information about testing a state using these inspection levels in the Step Functions console and AWS CLI, see Testing a state (Console) and Testing a state using AWS CLI.

INFO inspectionLevel

If the test succeeds, this level shows the state output. If the test fails, this level shows the error output. By default, Step Functions sets Inspection level to INFO if you don't specify a level.

The following image shows a test for a Pass state that succeeds. The Inspection level for this state is set to INFO and the output for the state appears in the Output tab.


                            Output of a selected state that succeeds a test for the INFO level.

The following image shows a test that failed for a Task state when the Inspection level is set to INFO. The Output tab shows the error output that includes the error name and a detailed explanation of the cause for that error.


                            Output of a selected state that succeeds a test for the INFO level.

DEBUG inspectionLevel

If the test succeeds, this level shows the state output and the result of input and output data processing.

If the test fails, this level shows the error output. This level shows the intermediate data processing results up to the point of failure. For example, say that you tested a Task state that invokes a Lambda function. Imagine that you had applied the InputPath, Parameters, ResultPath, and OutputPath filters to the Task state. Say that the invocation failed. In this case, the DEBUG level shows data processing results based on the application of the filters in the following order:

  • input – Raw state input

  • afterInputPath – Input after Step Functions applies the InputPath filter.

  • afterParameters – The effective input after Step Functions applies the Parameters filter.

The diagnostic information available in this level can help you troubleshoot issues related to a service integration or input and output data processing flow that you might have defined.

The following image shows a test for a Pass state that succeeds. The Inspection level for this state is set to DEBUG. The Input/output processing tab in the following image shows the result of the application of Parameters on the input provided for this state.


                            Output of a selected state that succeeds the test for the Debug level.

The following image shows a test that failed for a Task state when the Inspection level is set to DEBUG. The Input/output processing tab in the following image shows the input and output data processing result for the state up to the point of its failure.


                            Output of a state that failed the test for the Debug level.

TRACE inspectionLevel

Step Functions provides the TRACE level to test an HTTP Task. This level returns information about the HTTP request that Step Functions makes and response that a third-party API returns. The response might contain information, such as headers and request body. In addition, you can view the state output and result of input and output data processing in this level.

If the test fails, this level shows the error output.

This level is only applicable for HTTP Task. Step Functions throws an error if you use this level for other state types.

When you set the Inspection level to TRACE, you can also view secrets included in the EventBridge connection. To do this, you must set the revealSecrets parameter to true in the TestState API. In addition, you must make sure that the IAM user that calls the TestState API has permission for the states:RevealSecrets action. For an example of IAM policy that sets the states:RevealSecrets permission, see IAM permissions for using TestState API. Without this permission, Step Functions throws an access denied error.

If you set the revealSecrets parameter to false, Step Functions omits all secrets in the HTTP request and response data.

The following image shows a test for an HTTP Task that succeeds. The Inspection level for this state is set to TRACE. The HTTP request & response tab in the following image shows the result of the third-party API call.


                            Output of a selected state which succeeds the test for the TRACE level.

IAM permissions for using TestState API

The IAM user that calls the TestState API must have permissions to perform the states:TestState and iam:PassRole actions. In addition, if you set the revealSecrets parameter to true, you must make sure that the IAM user has permissions to perform the states:RevealSecrets action. Without this permission, Step Functions throws an access denied error.

You must also make sure that your execution role contains the required IAM permissions for the resources your state is accessing. For information about the permissions a state might need, see Managing execution roles.

The following IAM policy example sets the states:TestState, iam:PassRole, and states:RevealSecrets permissions.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "states:TestState", "states:RevealSecrets", "iam:PassRole" ], "Resource": "*" } ] }

Testing a state (Console)

You can test a state in the console and check the state output or input and output data processing flow. For an HTTP Task, you can test the raw HTTP request and response.

To test a state
  1. Open the Step Functions console.

  2. Choose Create state machine to start creating a state machine or choose an existing state machine.

  3. In the Design mode of Workflow Studio, choose a state that you want to test.

  4. Choose Test state in the Inspector panel of Workflow Studio.

  5. In the Test state dialog box, do the following:

    1. For Execution role, choose an execution role to test the state. Make sure that you have the required IAM permissions for the state that you want to test.

    2. (Optional) Provide any JSON input that your selected state needs for the test.

    3. For Inspection level, select one of the following options based on the values you want to view:

      • INFO – Shows the state output in the Output tab if the test succeeds. If the test fails, INFO shows the error output, which includes the error name and a detailed explanation of the cause for that error. By default, Step Functions sets Inspection level to INFO if you don't select a level.

      • DEBUG – Shows the state output and the result of input and output data processing if the test succeeds. If the test fails, DEBUG shows the error output, which includes the error name and a detailed explanation of the cause for that error.

      • TRACE – Shows the raw HTTP request and response, and is useful for verifying headers, query parameters, and other API-specific details. This option is only available for the HTTP Task.

        Optionally, you can choose to select Reveal secrets. In combination with TRACE, this setting lets you see the sensitive data that the EventBridge connection inserts, such as API keys. The IAM user identity that you use to access the console must have permission to perform the states:RevealSecrets action. Without this permission, Step Functions throws an access denied error when you start the test. For an example of an IAM policy that sets the states:RevealSecrets permission, see IAM permissions for using TestState API.

    4. Choose Start test.

Testing a state using AWS CLI

You can test a supported state using the TestState API in the AWS CLI. This API accepts the definition of a state and executes it.

For each state, you can specify the amount of detail you want to view in the test results. These details provide additional information about the state's execution, including its input and output data processing result and HTTP request and response information. The following examples showcase the different inspection levels you can specify for the TestState API. Remember to replace the italicized text with your resource-specific information.

This section contains the following examples that describe how you can use the different inspection levels that Step Functions provides in the AWS CLI:

Example 1: Using INFO inspectionLevel to test a Choice state

To test a state using the INFO inspectionLevel in the AWS CLI, run the test-state command as shown in the following example.

aws stepfunctions test-state \ --definition '{"Type": "Choice", "Choices": [{"Variable": "$.number", "NumericEquals": 1, "Next": "Equals 1"}, {"Variable": "$.number", "NumericEquals": 2, "Next": "Equals 2"}], "Default": "No Match"}' \ --role-arn arn:aws:iam::123456789012:role/myRole \ --input '{"number": 2}'

This example uses a Choice state to determine the execution path for the state based on the numeric input you provide. By default, Step Functions sets the inspectionLevel to INFO if you don't set a level.

Step Functions returns the following output.

{ "output": "{\"number\": 2}", "nextState": "Equals 2", "status": "SUCCEEDED" }

Example 2: Using DEBUG inspectionLevel to debug input and output data processing in a Pass state

To test a state using the DEBUG inspectionLevel in the AWS CLI, run the test-state command as shown in the following example.

aws stepfunctions test-state \ --definition '{"Type": "Pass", "InputPath": "$.payload", "Parameters": {"data": 1}, "ResultPath": "$.result", "OutputPath": "$.result.data", "Next": "Another State"}' \ --role-arn arn:aws:iam::123456789012:role/myRole \ --input '{"payload": {"foo": "bar"}}' \ --inspection-level DEBUG

This example uses a Pass state to showcase how Step Functions filters and manipulates input JSON data using the input and output data processing filters. This example uses these filters: InputPath, Parameters, ResultPath, and OutputPath.

Step Functions returns the following output.

{ "output": "1", "inspectionData": { "input": "{\"payload\": {\"foo\": \"bar\"}}", "afterInputPath": "{\"foo\":\"bar\"}", "afterParameters": "{\"data\":1}", "afterResultSelector": "{\"data\":1}", "afterResultPath": "{\"payload\":{\"foo\":\"bar\"},\"result\":{\"data\":1}}" }, "nextState": "Another State", "status": "SUCCEEDED" }

Example 3: Using TRACE inspectionLevel and revealSecrets to inspect the HTTP request sent to a third-party API

To test an HTTP Task using the TRACE inspectionLevel along with the revealSecrets parameter in the AWS CLI, run the test-state command as shown in the following example.

aws stepfunctions test-state \ --definition '{"Type": "Task", "Resource": "arn:aws:states:::http:invoke", "Parameters": {"Method": "GET", "Authentication": {"ConnectionArn": "arn:aws:events:us-east-1:123456789012:connection/MyConnection/0000000-0000-0000-0000-000000000000"}, "ApiEndpoint": "https://httpbin.org/get", "Headers": {"definitionHeader": "h1"}, "RequestBody": {"message": "Hello from Step Functions!"}, "QueryParameters": {"queryParam": "q1"}}, "End": true}' \ --role-arn arn:aws:iam::123456789012:role/myRole \ --inspection-level TRACE \ --reveal-secrets

This example tests if the HTTP Task calls the specified third-party API, https://httpbin.org/. It also shows the HTTP request and response data for the API call.

{ "output": "{\"Headers\":{\"date\":[\"Tue, 21 Nov 2023 00:06:17 GMT\"],\"access-control-allow-origin\":[\"*\"],\"content-length\":[\"620\"],\"server\":[\"gunicorn/19.9.0\"],\"access-control-allow-credentials\":[\"true\"],\"content-type\":[\"application/json\"]},\"ResponseBody\":{\"args\":{\"QueryParam1\":\"QueryParamValue1\",\"queryParam\":\"q1\"},\"headers\":{\"Authorization\":\"Basic XXXXXXXX\",\"Content-Type\":\"application/json; charset=UTF-8\",\"Customheader1\":\"CustomHeaderValue1\",\"Definitionheader\":\"h1\",\"Host\":\"httpbin.org\",\"Range\":\"bytes=0-262144\",\"Transfer-Encoding\":\"chunked\",\"User-Agent\":\"Amazon|StepFunctions|HttpInvoke|us-east-1\",\"X-Amzn-Trace-Id\":\"Root=1-0000000-0000-0000-0000-000000000000\"},\"origin\":\"12.34.567.891\",\"url\":\"https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1\"},\"StatusCode\":200,\"StatusText\":\"OK\"}", "inspectionData": { "input": "{}", "afterInputPath": "{}", "afterParameters": "{\"Method\":\"GET\",\"Authentication\":{\"ConnectionArn\":\"arn:aws:events:us-east-1:123456789012:connection/foo/a59c10f0-a315-4c1f-be6a-559b9a0c6250\"},\"ApiEndpoint\":\"https://httpbin.org/get\",\"Headers\":{\"definitionHeader\":\"h1\"},\"RequestBody\":{\"message\":\"Hello from Step Functions!\"},\"QueryParameters\":{\"queryParam\":\"q1\"}}", "result": "{\"Headers\":{\"date\":[\"Tue, 21 Nov 2023 00:06:17 GMT\"],\"access-control-allow-origin\":[\"*\"],\"content-length\":[\"620\"],\"server\":[\"gunicorn/19.9.0\"],\"access-control-allow-credentials\":[\"true\"],\"content-type\":[\"application/json\"]},\"ResponseBody\":{\"args\":{\"QueryParam1\":\"QueryParamValue1\",\"queryParam\":\"q1\"},\"headers\":{\"Authorization\":\"Basic XXXXXXXX\",\"Content-Type\":\"application/json; charset=UTF-8\",\"Customheader1\":\"CustomHeaderValue1\",\"Definitionheader\":\"h1\",\"Host\":\"httpbin.org\",\"Range\":\"bytes=0-262144\",\"Transfer-Encoding\":\"chunked\",\"User-Agent\":\"Amazon|StepFunctions|HttpInvoke|us-east-1\",\"X-Amzn-Trace-Id\":\"Root=1-0000000-0000-0000-0000-000000000000\"},\"origin\":\"12.34.567.891\",\"url\":\"https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1\"},\"StatusCode\":200,\"StatusText\":\"OK\"}", "afterResultSelector": "{\"Headers\":{\"date\":[\"Tue, 21 Nov 2023 00:06:17 GMT\"],\"access-control-allow-origin\":[\"*\"],\"content-length\":[\"620\"],\"server\":[\"gunicorn/19.9.0\"],\"access-control-allow-credentials\":[\"true\"],\"content-type\":[\"application/json\"]},\"ResponseBody\":{\"args\":{\"QueryParam1\":\"QueryParamValue1\",\"queryParam\":\"q1\"},\"headers\":{\"Authorization\":\"Basic XXXXXXXX\",\"Content-Type\":\"application/json; charset=UTF-8\",\"Customheader1\":\"CustomHeaderValue1\",\"Definitionheader\":\"h1\",\"Host\":\"httpbin.org\",\"Range\":\"bytes=0-262144\",\"Transfer-Encoding\":\"chunked\",\"User-Agent\":\"Amazon|StepFunctions|HttpInvoke|us-east-1\",\"X-Amzn-Trace-Id\":\"Root=1-0000000-0000-0000-0000-000000000000\"},\"origin\":\"12.34.567.891\",\"url\":\"https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1\"},\"StatusCode\":200,\"StatusText\":\"OK\"}", "afterResultPath": "{\"Headers\":{\"date\":[\"Tue, 21 Nov 2023 00:06:17 GMT\"],\"access-control-allow-origin\":[\"*\"],\"content-length\":[\"620\"],\"server\":[\"gunicorn/19.9.0\"],\"access-control-allow-credentials\":[\"true\"],\"content-type\":[\"application/json\"]},\"ResponseBody\":{\"args\":{\"QueryParam1\":\"QueryParamValue1\",\"queryParam\":\"q1\"},\"headers\":{\"Authorization\":\"Basic XXXXXXXX\",\"Content-Type\":\"application/json; charset=UTF-8\",\"Customheader1\":\"CustomHeaderValue1\",\"Definitionheader\":\"h1\",\"Host\":\"httpbin.org\",\"Range\":\"bytes=0-262144\",\"Transfer-Encoding\":\"chunked\",\"User-Agent\":\"Amazon|StepFunctions|HttpInvoke|us-east-1\",\"X-Amzn-Trace-Id\":\"Root=1-0000000-0000-0000-0000-000000000000\"},\"origin\":\"12.34.567.891\",\"url\":\"https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1\"},\"StatusCode\":200,\"StatusText\":\"OK\"}", "request": { "protocol": "https", "method": "GET", "url": "https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1", "headers": "[definitionHeader: h1, Authorization: Basic XXXXXXXX, CustomHeader1: CustomHeaderValue1, User-Agent: Amazon|StepFunctions|HttpInvoke|us-east-1, Range: bytes=0-262144]", "body": "{\"message\":\"Hello from Step Functions!\",\"BodyKey1\":\"BodyValue1\"}" }, "response": { "protocol": "https", "statusCode": "200", "statusMessage": "OK", "headers": "[date: Tue, 21 Nov 2023 00:06:17 GMT, content-type: application/json, content-length: 620, server: gunicorn/19.9.0, access-control-allow-origin: *, access-control-allow-credentials: true]", "body": "{\n \"args\": {\n \"QueryParam1\": \"QueryParamValue1\", \n \"queryParam\": \"q1\"\n }, \n \"headers\": {\n \"Authorization\": \"Basic XXXXXXXX\", \n \"Content-Type\": \"application/json; charset=UTF-8\", \n \"Customheader1\": \"CustomHeaderValue1\", \n \"Definitionheader\": \"h1\", \n \"Host\": \"httpbin.org\", \n \"Range\": \"bytes=0-262144\", \n \"Transfer-Encoding\": \"chunked\", \n \"User-Agent\": \"Amazon|StepFunctions|HttpInvoke|us-east-1\", \n \"X-Amzn-Trace-Id\": \"Root=1-0000000-0000-0000-0000-000000000000\"\n }, \n \"origin\": \"12.34.567.891\", \n \"url\": \"https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1\"\n}\n" } }, "status": "SUCCEEDED" }

Example 4: Using jq utility to filter and print the response that TestState API returns

The TestState API returns JSON data as escaped strings in its response. The following AWS CLI example extends Example 3 and uses the jq utility to filter and print the HTTP response that the TestState API returns in a human-readable format. For information about jq and its installation instructions, see jq on GitHub.

aws stepfunctions test-state \ --definition '{"Type": "Task", "Resource": "arn:aws:states:::http:invoke", "Parameters": {"Method": "GET", "Authentication": {"ConnectionArn": "arn:aws:events:us-east-1:123456789012:connection/MyConnection/0000000-0000-0000-0000-000000000000"}, "ApiEndpoint": "https://httpbin.org/get", "Headers": {"definitionHeader": "h1"}, "RequestBody": {"message": "Hello from Step Functions!"}, "QueryParameters": {"queryParam": "q1"}}, "End": true}' \ --role-arn arn:aws:iam::123456789012:role/myRole \ --inspection-level TRACE \ --reveal-secrets \ | jq '.inspectionData.response.body | fromjson'

The following example shows the output returned in a human-readable format.

{ "args": { "QueryParam1": "QueryParamValue1", "queryParam": "q1" }, "headers": { "Authorization": "Basic XXXXXXXX", "Content-Type": "application/json; charset=UTF-8", "Customheader1": "CustomHeaderValue1", "Definitionheader": "h1", "Host": "httpbin.org", "Range": "bytes=0-262144", "Transfer-Encoding": "chunked", "User-Agent": "Amazon|StepFunctions|HttpInvoke|us-east-1", "X-Amzn-Trace-Id": "Root=1-0000000-0000-0000-0000-000000000000" }, "origin": "12.34.567.891", "url": "https://httpbin.org/get?queryParam=q1&QueryParam1=QueryParamValue1" }

Testing and debugging input and output data flow

The TestState API is helpful for testing and debugging the data that flows through your workflow. This section provides some key concepts and explains how to use the TestState for this purpose.

Key concepts

In Step Functions, the process of filtering and manipulating JSON data as it passes through the states in your state machine is called input and output processing. For information about how this works, see Input and Output Processing in Step Functions.

All the state types in the Amazon States Language (ASL) (Task, Parallel, Map, Pass, Wait, Choice, Succeed, and Fail) share a set of common fields for filtering and manipulating the JSON data that passes through them. These fields are: InputPath, Parameters, ResultSelector, ResultPath, and OutputPath. Support for each field varies across states. At runtime, Step Functions applies each field in a specific order. The following diagram shows the order in which these fields are applied to the data inside a Task state:


                    The order in which Step Functions applies the input and output data processing filters: InputPath, Parameters, ResultSelector, ResultPath and OutputPath to a state.

The following list describes the order of application of the input and output processing fields shown in the diagram.

  1. State input is the JSON data passed to the current state from a previous state.

  2. InputPath filters a portion of the raw state input.

  3. Parameters configures the set of values to pass to the Task.

  4. The task performs work and returns a result.

  5. ResultSelector selects a set of values to keep from the task result.

  6. ResultPath combines the result with the raw state input, or replaces the result with it.

  7. OutputPath filters a portion of the output to pass along to the next state.

  8. State output is the JSON data passed from the current state to the next state.

These input and output processing fields are optional. If you don’t use any of these fields in your state definition, the task will consume the raw state input, and return the task result as the state output.

Using TestState to inspect input and output processing

When you call the TestState API and set the inspectionLevel parameter to DEBUG, the API response includes an object called inspectionData. This object contains fields to help you inspect how data was filtered or manipulated within the state when it was executed. The following example shows the inspectionData object for a Task state.

"inspectionData": { "input": string, "afterInputPath": string, "afterParameters": string, "result": string, "afterResultSelector": string, "afterResultPath": string, "output": string }

In this example, each field that contains the after prefix, shows the data after a particular field was applied. For example, afterInputPath shows the effect of applying the InputPath field to filter the raw state input. The following diagram maps each ASL definition field to its corresponding field in the inspectionData object:


                    The mapping of the inspectionData object fields with ASL fields.

For examples of using the TestState API to debug input and output processing, see the following: