在 Step Functions 中使用 TestState API 测试状态
TestState API 会接受单个状态的定义并执行它。您无需创建状态机或更新现有状态机,即可测试状态。
使用 TestState API,您可以测试以下各项:
-
状态的输入和输出处理数据流。
-
与其他 AWS 服务请求和响应的 AWS 服务集成
-
HTTP 任务请求和响应
要测试状态,您还可以使用 Step Functions 控制台、AWS Command Line Interface (AWS CLI) 或 SDK。
TestState API 扮演一个 IAM 角色,该角色必须针对状态访问的资源包含必需的 IAM 权限。有关状态可能需要的权限的信息,请参阅使用 TestState API 的 IAM 权限。
主题
使用 TestState API 时的注意事项
使用 TestState API,您一次只能测试一个状态。您可以测试的状态包括:
在使用 TestState API 时,请记住以下注意事项。
-
TestState API 不包含对以下各项的支持:
-
Task 工作流程状态使用以下资源类型的 状态:
-
Map 状态工作流程。 状态
-
-
测试最多可以运行五分钟。如果测试超过此持续时间,则会因
States.Timeout错误而失败。
在 TestState API 中使用检查级别
要使用 TestState API 测试状态,您需要提供该状态的定义。然后,测试返回输出。对于每种状态,您可以指定要在测试结果中查看的详细信息量。这些详细信息提供有关您要测试的状态的更多信息。例如,如果您使用了任何输入和输出数据处理筛选器,例如状态中的 InputPath 或 ResultPath,则可以查看中间和最终的数据处理结果。
Step Functions 提供以下级别,供您指定要查看的详细信息:
所有这些级别还会返回 status 和 nextState 字段。status 表示状态执行的状态。例如,SUCCEEDED、FAILED、RETRIABLE 和 CAUGHT_ERROR。nextState 表示要过渡到的下一个状态的名称。如果您尚未在定义中定义下一个状态,则此字段会返回一个空值。
有关在 Step Functions 控制台和 AWS CLI 中使用这些检查级别测试状态的信息,请参阅测试状态(控制台)和使用 AWS CLI 测试状态。
“信息”检查级别
如果测试成功,此级别会显示状态输出。如果测试失败,此级别会显示错误输出。默认情况下,如果您未指定级别,Step Functions 会将检查级别设置为信息。
下图显示了成功的 Pass 状态测试。此状态的检查级别设置为信息,该状态的输出显示在输出选项卡中。
下图显示了当检查级别设置为信息时失败的 Task 状态测试。输出选项卡会显示错误输出,其中包含错误名称和错误原因的详细说明。
“调试”检查级别
如果测试成功,此级别会显示状态输出以及输入和输出数据处理的结果。
如果测试失败,此级别会显示错误输出。此级别显示最多到故障点的中间数据处理结果。例如,假设您测试了一个调用 Lambda 函数的 Task 状态。想象一下,您已向 Task 状态应用 InputPath、参数、在 Step Functions 中使用 ResultPath 指定状态输出 和 使用 OutputPath 筛选状态输出 筛选器。假设调用失败。在此例中,DEBUG 级别基于应用的筛选器按以下顺序显示数据处理结果:
-
input:原始状态输入 -
afterInputPath:Step Functions 应用InputPath筛选器后的输入。 -
afterParameters:Step Functions 应用Parameters筛选器后的有效输入。
此级别中提供的诊断信息可以帮助您排查与服务集成或您可能已定义的输入和输出数据处理流相关的问题。
下图显示了成功的 Pass 状态测试。此状态的检查级别设置为调试。下图中的输入/输出处理选项卡显示了在针对提供的输入应用 Parameters 后此状态的结果。
下图显示了当检查级别设置为调试时失败的 Task 状态测试。下图中的输入/输出处理选项卡显示了此状态最多到故障点的输入和输出数据处理结果。
“跟踪”检查级别
Step Functions 提供用于测试 HTTP 任务的跟踪级别。此级别会返回有关 Step Functions 发出的 HTTP 请求和 HTTPS API 返回的响应的信息。响应可能包含标头和请求正文等信息。此外,您还可以在此级别查看状态输出以及输入和输出数据处理的结果。
如果测试失败,此级别会显示错误输出。
此级别仅适用于 HTTP 任务。如果您将此级别用于其他状态类型,则 Step Functions 会抛出错误。
将检查级别设置为跟踪时,您还可以查看 EventBridge 连接中包含的密钥。为此,您必须在 TestState API 中将 revealSecrets 参数设置为 true。此外,您必须确保调用 TestState API 的 IAM 用户拥有 states:RevealSecrets 操作的权限。有关设置 states:RevealSecrets 权限的 IAM 策略示例,请参阅使用 TestState API 的 IAM 权限。如果没有此权限,则 Step Functions 会抛出访问遭拒错误。
如果您将 revealSecrets 参数设置为 false,则 Step Functions 会省略 HTTP 请求和响应数据中的所有密钥。
下图显示了成功的 HTTP 任务测试。此状态的检查级别设置为跟踪。下图中的 HTTP 请求和响应选项卡显示了 HTTPS API 调用的结果。
使用 TestState API 的 IAM 权限
调用 TestState API 的 IAM 用户必须有权执行 states:TestState 和 iam:PassRole 操作。
此外,如果您将 revealSecrets 参数设置为 true,则必须确保 IAM 用户有权执行 states:RevealSecrets 操作。如果没有此权限,则 Step Functions 会抛出访问遭拒错误。
此外,对于您的状态访问的资源,您还必须确保执行角色包含必需的权限。有关状态可能需要的权限的信息,请参阅管理执行角色。
测试状态(控制台)
您可以在控制台中测试状态,并检查状态输出或输入和输出数据处理流。对于 HTTP 任务,您可以测试原始 HTTP 请求和响应。
测试状态
-
选择创建状态机开始创建状态机,或选择一个现有状态机。
-
在 Workflow Studio 的设计模式中,选择要测试的状态。
-
从 Workflow Studio 的 检查器面板 面板中选择测试状态。
-
在测试状态对话框中,执行以下操作:
-
对于执行角色,选择一个执行角色来测试状态。请确保您对要测试的状态具有必需的 IAM 权限。
-
(可选)针对测试提供所选状态需要的任何 JSON 输入。
-
对于检查级别,根据要查看的值选择以下选项之一:
-
信息:如果测试成功,此级别会在输出选项卡中显示状态输出。如果测试失败,信息级别会显示错误输出,其中包含错误名称和错误原因的详细说明。默认情况下,如果您未选择级别,Step Functions 会将检查级别设置为信息。
-
调试:如果测试成功,此级别会显示状态输出以及输入和输出数据处理的结果。如果测试失败,调试级别会显示错误输出,其中包含错误名称和错误原因的详细说明。
-
跟踪:此级别会显示原始的 HTTP 请求和响应,对于验证标头、查询参数和其他特定于 API 的详细信息非常有用。此选项仅适用于 HTTP 任务。
您可以根据需要选择显示密钥。结合跟踪检查级别,此设置可让您查看 EventBridge 连接插入的敏感数据,例如 API 密钥。您用于访问控制台的 IAM 用户身份必须具有执行
states:RevealSecrets操作的权限。如果没有此权限,则在您开始测试时 Step Functions 会抛出访问遭拒错误。有关设置states:RevealSecrets权限的 IAM 策略示例,请参阅使用 TestState API 的 IAM 权限。
-
-
选择开始测试。
-
使用 AWS CLI 测试状态
您可以使用 AWS CLI 中的 TestState API 来测试支持的状态。此 API 会接受状态的定义并执行它。
对于每种状态,您可以指定要在测试结果中查看的详细信息量。这些详细信息提供有关状态执行的额外信息,包括其输入和输出数据处理结果以及 HTTP 请求和响应信息。以下示例展示了您可以为 TestState API 指定的不同检查级别。切记用特定资源信息替换斜体文本。
本部分包含以下示例,它们说明了如何使用 Step Functions 在 AWS CLI 中提供的不同检查级别:
示例 1:使用 INFO inspectionLevel 来测试 Choice 状态
要在 AWS CLI 中使用 INFO inspectionLevel 测试状态,请运行 test-state 命令,如以下示例中所示。
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::account-id:role/myRole\ --input '{"number": 2}'
此示例使用 Choice 状态根据您提供的数字输入来确定该状态的执行路径。默认情况下,如果您未设置级别,Step Functions 会将 inspectionLevel 设置为 INFO。
Step Functions 返回以下输出:
{
"output": "{\"number\": 2}",
"nextState": "Equals 2",
"status": "SUCCEEDED"
}
示例 2:使用 DEBUG inspectionLevel 针对 Pass 状态调试输入和输出数据处理
要在 AWS CLI 中使用 DEBUG inspectionLevel 测试状态,请运行 test-state 命令,如以下示例中所示。
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::account-id:role/myRole\ --input '{"payload": {"foo": "bar"}}' \ --inspection-level DEBUG
此示例使用 Pass 工作流程状态 状态来展示 Step Functions 如何使用输入和输出数据处理筛选器来筛选和处理输入 JSON 数据。此示例使用以下筛选器:InputPath、参数、在 Step Functions 中使用 ResultPath 指定状态输出 和 使用 OutputPath 筛选状态输出。
Step Functions 返回以下输出:
{
"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"
}
示例 3:使用 TRACE inspectionLevel 和 revealSecrets 检查发送到 HTTPS API 的 HTTP 请求
要在 AWS CLI 中使用 TRACE inspectionLevel 以及 revealSecrets 参数测试 HTTP 任务,请运行 test-state 命令,如以下示例所示。
aws stepfunctions test-state \
--definition '{"Type": "Task", "Resource": "arn:aws:states:::http:invoke", "Parameters": {"Method": "GET", "Authentication": {"ConnectionArn": "arn:aws:events:region:account-id: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::account-id:role/myRole \
--inspection-level TRACE \
--reveal-secrets
此示例测试 HTTP 任务是否会调用指定的 HTTPS API,https://httpbin.org/。它还会显示 API 调用的 HTTP 请求和响应数据。
{
"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|region\",\"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:region:account-id: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|region\",\"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|region\",\"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|region\",\"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|region, 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|region\", \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"
}
示例 4:使用 jq 实用程序筛选和输出 TestState API 返回的响应
TestState API 在其响应中以转义字符串的形式返回 JSON 数据。以下 AWS CLI 示例对示例 3 进行了扩展,使用 jq 实用程序筛选和输出 TestState API 以人类可读的格式返回的 HTTP 响应。有关 jq 和其安装说明的信息,请参阅 GitHub 上的 jq
aws stepfunctions test-state \
--definition '{"Type": "Task", "Resource": "arn:aws:states:::http:invoke", "Parameters": {"Method": "GET", "Authentication": {"ConnectionArn": "arn:aws:events:region:account-id: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::account-id:role/myRole \
--inspection-level TRACE \
--reveal-secrets \
| jq '.inspectionData.response.body | fromjson'
以下示例显示了以人类可读的格式返回的输出。
{
"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|region",
"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"
}
测试和调试输入和输出数据流
TestState API 有助于测试和调试流经您的工作流的数据。本部分提供了一些重要概念,并说明了如何将 TestState 用于此目的。
重要概念
在 Step Functions 中,在 JSON 数据经历状态机中的状态时对其进行筛选和处理的过程称为输入和输出处理。有关其工作方式的信息,请参阅在 Step Functions 中处理输入和输出。
Amazon States Language (ASL) 中的所有状态类型(Task、Parallel、Map、Pass、Wait、Choice、Succeed 和 Fail)共用一组公共字段,来筛选和处理经历它们的 JSON 数据。这些字段包括:InputPath、参数、ResultSelector、在 Step Functions 中使用 ResultPath 指定状态输出 和 使用 OutputPath 筛选状态输出。对每个字段的支持因状态而异
以下列表说明了图中显示的输入和输出处理字段的应用顺序。
-
状态输入是从先前状态传递到当前状态的 JSON 数据。
-
InputPath 筛选部分原始状态输入。
-
任务执行工作并返回结果。
-
ResultSelector 从任务结果中选择一组要保留的值。
-
在 Step Functions 中使用 ResultPath 指定状态输出 将结果与原始状态输入合并,或者用它替换结果。
-
使用 OutputPath 筛选状态输出 筛选输出的一部分以传递到下一状态。
-
状态输出是从当前状态传递到下一状态的 JSON 数据。
这些输入和输出处理字段是可选的。如果您在状态定义中未使用这些字段中的任何一个,则任务将使用原始状态输入,并将任务结果作为状态输出返回。
使用 TestState 检查输入和输出处理
当您调用 TestState API 并将 inspectionLevel 参数设置为 DEBUG 时,API 响应会包含一个名为 inspectionData 的对象。此对象包含一些字段,可帮助您检查在相应状态执行时,数据是如何筛选或处理的。以下示例显示了 Task 状态的 inspectionData 对象。
"inspectionData": {
"input": string,
"afterInputPath": string,
"afterParameters": string,
"result": string,
"afterResultSelector": string,
"afterResultPath": string,
"output": string
}
在此示例中,每个包含 after 前缀的字段都显示特定字段应用后的数据。例如,afterInputPath 显示应用 InputPath 字段以筛选原始状态输入的效果。下图将每个 ASL 定义字段映射到 inspectionData 对象中的相应字段:
有关使用 TestState API 调试输入和输出处理的示例,请参阅以下内容: