AWS IoT Greengrass Version 1 於 2023 年 6 月 30 日進入延長壽命階段。如需詳細資訊,請參閱 AWS IoT Greengrass V1 維護政策 。在此日期之後, AWS IoT Greengrass V1 不會發佈提供功能、增強功能、錯誤修正或安全修補程式的更新。在 上執行的裝置 AWS IoT Greengrass V1 不會中斷,並會繼續運作和連線至雲端。我們強烈建議您遷移至 AWS IoT Greengrass Version 2,這會新增重要的新功能,並支援其他平台 。
本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
配置 IDT 狀態機
狀態機是控制測試套件執行流程的構造。它確定測試套件的起始狀態,根據用户定義的規則管理狀態轉換,並繼續在這些狀態之間進行轉換,直到它達到結束狀態。
如果您的測試套件不包含用户定義的狀態機,IDT 將為您生成一個狀態機。默認狀態機執行以下功能:
-
為測試運行者提供選擇和運行特定測試組的能力,而不是整個測試套件。
-
如果未選擇特定測試組,則以隨機順序運行測試套件中的每個測試組。
-
生成報告並打印顯示每個測試組和測試用例的測試結果的控制台摘要。
IDT 測試套件的狀態機器必須滿足下列條件:
-
每個狀態對應於 IDT 要執行的操作,例如運行測試組或產品報告文件。
-
轉換到狀態將執行與狀態關聯的操作。
-
每個狀態都定義下一個狀態的過渡規則。
-
終止狀態必須為
Succeed
或者Fail
。
狀態機器格式
您可以使用以下模板配置您自己的
文件: <custom-test-suite-folder>
/suite/state_machine.json
{ "Comment": "
<description>
", "StartAt": "<state-name>
", "States": { "<state-name>
": { "Type": "<state-type>
", // Additional state configuration } // Required states "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }
如下所述,包含值的所有欄位皆為必要:
Comment
-
狀態機器的描述。
StartAt
-
IDT 開始運行測試套件的名稱。的值
StartAt
必須設定為States
物件。 States
-
將用户定義的狀態名稱映射到有效 IDT 狀態的對象。每個國家.
狀態名稱
對象包含映射到狀態名稱
。所以此
States
對象必須包含Succeed
和Fail
狀態。如需有效狀態的資訊,請參有效的狀態和狀態定義。
有效的狀態和狀態定義
本節介紹 IDT 狀態機中可以使用的所有有效狀態的狀態定義。以下某些狀態支持測試用例級別的配置。但是,除非絕對必要,否則我們建議您在測試組級別而不是在測試用例級別配置狀態轉換規則。
RunTask
所以此RunTask
狀態從測試套件中定義的測試組中運行測試用例。
{ "Type": "RunTask", "Next": "
<state-name>
", "TestGroup": "<group-id>
", "TestCases": [ "<test-id>
" ], "ResultVar": "<result-name>
" }
如下所述,包含值的所有欄位皆為必要:
Next
-
在當前狀態下執行動作後轉換至的名稱。
TestGroup
-
選用。要運行的測試組的 ID。如果未指定此值,則 IDT 運行測試運行程序選擇的測試組。
TestCases
-
選用。測試用例 ID 的數組
TestGroup
。基於TestGroup
和TestCases
,IDT 確定測試執行行為,如下所示:-
當兩者
TestGroup
和TestCases
時,IDT 將從測試組運行指定的測試用例。 -
時機
TestCases
,但TestGroup
,則 IDT 運行指定的測試用例。 -
時機
TestGroup
,但TestCases
,IDT 會運行指定測試組中的所有測試用例。 -
當兩者都沒有
TestGroup
或者TestCases
時,IDT 運行測試運行者從 IDT CLI 中選擇的測試組中的所有測試用例。要為測試運行者啟用組選擇,必須同時包含RunTask
和Choice
狀態statemachine.json
file. 如需此作業的範例,請參範例狀態機器:運行用户選定的測試組。如需為測試運行者啟用 IDT CLI 命令的詳細資訊,請參啟用 IDT CLI 命令。
-
ResultVar
-
要使用測試運行結果設置的上下文變量的名稱。如果未指定
TestGroup
。IDT 設置您在ResultVar
至true
或者false
會根據下列的規則:-
如果變量名稱為
,則該值將設置為第一個測試組中的所有測試是通過還是被跳過。text
_text
_passed -
在所有其他情況下,該值都設置為所有測試組中的所有測試都通過還是跳過。
-
一般而言,您需要使用RunTask
狀態指定測試組 ID,而不指定單個測試用例 ID,以便 IDT 將運行指定測試組中的所有測試用例。由此狀態運行的所有測試用例以隨機順序 parallel 運行。但是,如果所有測試用例都要求設備運行,並且只有一個設備可用,則測試用例將按順序運行。
錯誤處理
如果任何指定的測試組或測試用例 ID 無效,則此狀態會發出RunTaskError
執行錯誤。如果狀態遇到執行錯誤,則它還會設置hasExecutionError
變量設置為true
。
Choice
所以此Choice
狀態允許您根據用户定義的條件動態設置要轉換到的下一個狀態。
{ "Type": "Choice", "Default": "
<state-name>
", "FallthroughOnError": true | false, "Choices": [ { "Expression": "<expression>
", "Next": "<state-name>
" } ] }
如下所述,包含值的所有欄位皆為必要:
Default
-
如果未定義中的任何表達式,則為默認狀態轉換至。
Choices
可以評估為true
。 FallthroughOnError
-
選用。指定狀態在計算表達式時遇到錯誤時的行為。設定為
true
如果您想在評估導致錯誤時跳過表達式。如果沒有匹配的表達式,則狀態機器會轉換到Default
狀態。如果FallthroughOnError
值,則默認為false
。 Choices
-
一個表達式和狀態數組,用於確定在當前狀態下執行操作後轉換到哪個狀態。
Choices.Expression
-
計算為布爾值的表達式字符串。如果表達式的計算結果為
true
,則狀態機器會轉換到Choices.Next
。表達式字符串從狀態機上下文中檢索值,然後對它們執行操作以獲得布爾值。有關訪問狀態機上下文的信息,請參閲狀態機器上下文。 Choices.Next
-
如果在
Choices.Expression
評估為true
。
錯誤處理
所以此Choice
狀態可能需要在下列情況下進行錯誤處理:
-
選擇表達式中的某些變量在狀態機上下文中不存在。
-
表達式的結果不是布爾值。
-
JSON 查找的結果不是字符串、數字或布爾值。
您無法使用Catch
塊來處理此狀態下的錯誤。如果要在遇到錯誤時停止執行狀態機,則必須將FallthroughOnError
至false
。不過,建議您將FallthroughOnError
至true
,並根據您的用例,執行下列其中一項操作:
-
如果您正在訪問的變量在某些情況下預期不存在,則使用
Default
和其他Choices
塊來指定下一個狀態。 -
如果您正在訪問的變量應該始終存在,則設置
Default
狀態Fail
。
平行
所以此Parallel
狀態允許您彼此並行定義和運 parallel 新的狀態機。
{ "Type": "Parallel", "Next": "
<state-name>
", "Branches": [<state-machine-definition>
] }
如下所述,包含值的所有欄位皆為必要:
Next
-
在當前狀態下執行動作後轉換至的名稱。
Branches
-
要運行的狀態機定義數組。每個狀態機器定義都必須包含其自己的
StartAt
、Succeed
,和Fail
狀態。此數組中的狀態機定義不能引用其自身定義之外的狀態。注意
由於每個分支狀態機共享相同的狀態機上下文,所以在一個分支中設置變量,然後從另一個分支讀取這些變量可能會導致意外的行為。
所以此Parallel
狀態只有在運行所有分支狀態計算機後才會移動到下一個狀態。需要設備的每個狀態都將等待運行,直到設備可用。如果有多個設備可用,則此狀態從多個組並行運 parallel 測試用例。如果沒有足夠的設備可用,則測試用例將按順序運行。由於測試用例在並行運行時以隨機順序運 parallel,因此可能會使用不同的設備從同一測試組運行測試。
錯誤處理
確保分支狀態機和父狀態機都轉換到Fail
狀態來處理執行錯誤。
由於分支狀態計算機不會將執行錯誤傳輸到父狀態機,因此不能使用Catch
塊來處理分支狀態計算機中的執行錯誤。而是使用hasExecutionErrors
值在共享狀態機上下文中。如需此作業的範例,請參範例狀態機器:parallel 行運行兩個測試組。
添加產品功能
所以此AddProductFeatures
狀態允許您將產品功能添加到awsiotdevicetester_report.xml
文件由 IDT 生成。
產品功能是用户定義的有關設備可能滿足的特定條件的信息。例如,MQTT
產品功能可以指定設備正確發佈 MQTT 消息。在報告中,產品功能設置為supported
、not-supported
或自定義值,具體取決於是否通過指定的測試。
注意
所以此AddProductFeatures
狀態不會自行生成報告。此狀態必須轉換為Reportstate以生成報告。
{ "Type": "Parallel", "Next": "
<state-name>
", "Features": [ { "Feature": "<feature-name>
", "Groups": [ "<group-id>
" ], "OneOfGroups": [ "<group-id>
" ], "TestCases": [ "<test-id>
" ], "IsRequired": true | false, "ExecutionMethods": [ "<execution-method>
" ] } ] }
如下所述,包含值的所有欄位皆為必要:
Next
-
在當前狀態下執行動作後轉換至的名稱。
Features
-
一組產品功能顯示在
awsiotdevicetester_report.xml
file.Feature
-
功能的名稱
FeatureValue
-
選用。要在報表中使用的自定義值,而不是
supported
。如果未指定此值,則根據測試結果,將要素值設置為supported
或者not-supported
。如果您將自定義值用於
FeatureValue
,則可以在不同條件下測試同一要素,並且 IDT 會連接受支持條件的特徵值。例如,下列摘錄顯示MyFeature
功能具有兩個獨立的要素值:... { "Feature": "MyFeature", "FeatureValue": "first-feature-supported", "Groups": ["first-feature-group"] }, { "Feature": "MyFeature", "FeatureValue": "second-feature-supported", "Groups": ["second-feature-group"] }, ...
如果兩個測試組均通過,則要素值設置為
first-feature-supported, second-feature-supported
。 Groups
-
選用。測試組 ID 陣列。每個指定測試組中的所有測試都必須通過,才能支持該功能。
OneOfGroups
-
選用。測試組 ID 陣列。至少一個指定測試組中的所有測試必須通過,才能支持該功能。
TestCases
-
選用。測試用例 ID 陣列。如果指定此值,則以下內容適用:
-
必須通過所有指定的測試用例,才能支持該功能。
-
Groups
必須僅包含一個測試組 ID。 -
OneOfGroups
必須指定。
-
IsRequired
-
選用。設定為
false
將此功能標記為報告中的可選功能。預設值為true
。 ExecutionMethods
-
選用。一個執行方法的數組,它們匹配
protocol
中指定的值device.json
file. 如果指定了此值,則測試運行者必須指定protocol
值,該值與此數組中的某個值匹配,以便在報告中包含該功能。如果未指定此值,則該功能將始終包含在報告中。
若要使用 AWS for WordPressAddProductFeatures
狀態,則必須將ResultVar
中的RunTask
狀態設定為下列其中一個值:
-
如果您指定了單個測試用例 ID,則設置
ResultVar
至
。group-id_test-id
_passed -
如果您沒有指定單個測試用例 ID,則設置
ResultVar
至
。group-id
_passed
所以此AddProductFeatures
狀態會按下列方式檢查測試結果:
-
如果未指定任何測試用例 ID,則每個測試組的結果將根據
變量在狀態機上下文中。group-id
_passed -
如果您確實指定了測試用例 ID,則每個測試的結果將根據
變量在狀態機上下文中。group-id_test-id
_passed
錯誤處理
如果在此狀態下提供的組 ID 不是有效的組 ID,則此狀態會導致AddProductFeaturesError
執行錯誤。如果狀態遇到執行錯誤,則它還會設置hasExecutionErrors
變量設置為true
。
報告
所以此Report
狀態會生成
和suite-name
_Report.xmlawsiotdevicetester_report.xml
檔案。此狀態還會將報告流式傳輸到控制台。
{ "Type": "Report", "Next": "
<state-name>
" }
如下所述,包含值的所有欄位皆為必要:
Next
-
在當前狀態下執行動作後轉換至的名稱。
您應始終轉換到Report
狀態,以便測試運行者可以查看測試結果。通常情況下,此狀態之後的下一個狀態是Succeed
。
錯誤處理
如果此狀態在生成報告時遇到問題,則會發出ReportError
執行錯誤。
日誌消息
所以此LogMessage
狀態會生成test_manager.log
文件並將日誌消息流式傳輸到主控台。
{ "Type": "LogMessage", "Next": "
<state-name>
" "Level": "info | warn | error" "Message": "<message>
" }
如下所述,包含值的所有欄位皆為必要:
Next
-
在當前狀態下執行動作後轉換至的名稱。
Level
-
創建日誌消息的錯誤級別。如果指定的級別無效,此狀態將生成一條錯誤消息並將其丟棄。
Message
-
要記錄的消息。
選擇組
所以此SelectGroup
狀態會更新狀態機上下文以指示選擇哪些組。由此狀態設置的值由任何後續Choice
狀態。
{ "Type": "SelectGroup", "Next": "
<state-name>
" "TestGroups": [<group-id>
" ] }
如下所述,包含值的所有欄位皆為必要:
Next
-
在當前狀態下執行動作後轉換至的名稱。
TestGroups
-
將標記為選定的測試組的數組。對於此陣列中的每個測試組 ID,
變量設置為group-id
_selectedtrue
在上下文中。請確保您提供有效的測試組 ID,因為 IDT 不會驗證指定的組是否存在。
Fail
所以此Fail
狀態表示狀態機未正確執行。這是狀態機的結束狀態,每個狀態機定義都必須包含此狀態。
{ "Type": "Fail" }
Succeed
所以此Succeed
狀態表示狀態機正確執行。這是狀態機的結束狀態,每個狀態機定義都必須包含此狀態。
{ "Type": "Succeed" }
狀態機器上下文
狀態機上下文是一個只讀的 JSON 文檔,其中包含在執行期間可供狀態機使用的數據。狀態機上下文只能從狀態機訪問,幷包含確定測試流的信息。例如,您可以使用測試運行者在userdata.json
文件來確定是否需要特定測試才能運行。
狀態機器上下文使用下列格式:
{ "pool": {
<device-json-pool-element>
}, "userData": {<userdata-json-content>
}, "config": {<config-json-content>
}, "suiteFailed": true | false, "specificTestGroups": [ "<group-id>" ], "specificTestCases": [ "<test-id>" ], "hasExecutionErrors": true }
pool
-
有關為測試運行選擇的設備池的信息。對於選定的設備池,此信息將從
device.json
file. userData
-
中的資訊
userdata.json
file. config
-
信息固定
config.json
file. suiteFailed
-
此值設定為
false
當狀態機器啟動時。如果測試組在RunTask
狀態,則此值將設置為true
執行狀態機器的剩餘持續時間。 specificTestGroups
-
如果測試運行者選擇要運行的特定測試組而不是整個測試套件,則會創建此項並且包含特定測試組 ID 的列表。
specificTestCases
-
如果測試運行者選擇要運行的特定測試用例而不是整個測試套件,則會創建此密鑰並包含特定測試用例 ID 的列表。
hasExecutionErrors
-
狀態機啟動時不退出。如果任何狀態遇到執行錯誤,則會創建此變量並將其設置為
true
執行狀態機器的剩餘持續時間。
您可以使用 JSONPath 表示法查詢上下文。狀態定義中的 JSONPath 查詢的語法是{{$.
。您可以在某些狀態中使用 JSONPath 查詢作為佔位符字符串。IDT 將佔位符字符串替換為從上下文中評估的 JSONPath 查詢的值。您可以使用佔位符作為下列值:query
}}
-
所以此
TestCases
中的值RunTask
狀態。 -
所以此
Expression
值Choice
狀態。
當您從狀態機器上下文訪問數據時,請確保滿足下列條件:
-
您的 JSON 路徑必須以
$.
-
每個值都必須計算為字符串、數字或布爾值。
如需使用 JSONPath 符號從上下文訪問數據的詳細資訊,請參使用 IDT 上下文。
執行錯誤
執行錯誤是狀態機在執行狀態時遇到的狀態機定義中的錯誤。IDT 將有關每個錯誤的信息記錄在test_manager.log
文件並將日誌消息流式傳輸到主控台。
您可以使用下列方法來處理執行錯誤:
-
新增Catch塊在狀態定義中。
-
檢查hasExecutionErrors值中的狀態機器。
抓
使用Catch
中,將以下內容添加到您的狀態定義中:
"Catch": [ { "ErrorEquals": [ "
<error-type>
" ] "Next": "<state-name>
" } ]
如下所述,包含值的所有欄位皆為必要:
Catch.ErrorEquals
-
要 catch 的錯誤類型的數組。如果執行錯誤與其中一個指定的值匹配,則狀態機器會轉換到
Catch.Next
。有關其產生的錯誤類型的信息,請參閲每個狀態定義。 Catch.Next
-
如果當前狀態遇到與
Catch.ErrorEquals
。
Catch 塊按順序處理,直到一個匹配。如果沒有錯誤與 Catch 塊中列出的錯誤匹配,則狀態計算機將繼續執行。由於執行錯誤是由不正確的狀態定義導致的,因此建議您在狀態遇到執行錯誤時轉換為「失敗」狀態。
哈希執行錯誤
當某些狀態遇到執行錯誤時,除了發出錯誤之外,它們還設置hasExecutionError
值設定為true
在狀態機器上下文中。您可以使用此值檢測錯誤何時發生,然後使用Choice
狀態將狀態機轉換為Fail
狀態。
此方法具有下列特性。
-
狀態機不以分配給
hasExecutionError
,並且在特定狀態設置之前,此值不可用。這意味着您必須顯式設定FallthroughOnError
至false
(針對)Choice
狀態訪問此值,以防止狀態機在沒有發生執行錯誤時停止。 -
一旦它被設置為
true
、hasExecutionError
永遠不會設置為 false 或從上下文中刪除。這意味着此值僅在第一次設置為true
,並且對於所有後續狀態,它不提供一個有意義的值。 -
所以此
hasExecutionError
值共享給Parallel
狀態,這可能會導致意外的結果,具體取決於訪問它的順序。
由於這些特性,如果您可以使用 Catch 塊,我們不建議您使用此方法。
範例狀態機器
本節提供狀態機器配置範例。
範例狀態機器:運行單個測試組
此狀態機器:
-
運行 ID 的測試組
GroupA
,它必須存在於group.json
file. -
檢查執行錯誤和過渡到
Fail
(如果找到任何)。 -
生成報告並過渡到
Succeed
如果沒有錯誤,Fail
否則為。
{ "Comment": "Runs a single group and then generates a report.", "StartAt": "RunGroupA", "States": { "RunGroupA": { "Type": "RunTask", "Next": "Report", "TestGroup": "GroupA", "Catch": [ { "ErrorEquals": [ "RunTaskError" ], "Next": "Fail" } ] }, "Report": { "Type": "Report", "Next": "Succeed", "Catch": [ { "ErrorEquals": [ "ReportError" ], "Next": "Fail" } ] }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }
範例狀態機器:運行用户選定的測試組
此狀態機器:
-
檢查測試運行者是否選擇了特定的測試組。狀態機不檢查特定測試用例,因為測試運行者不同時選擇測試組就無法選擇測試用例。
-
如果選定了測試組:
-
在選定測試組中運行測試用例。為此,狀態機不會在
RunTask
狀態。 -
運行所有測試並退出後生成報告。
-
-
如果未選擇測試組:
-
在測試組中運行測試
GroupA
。 -
生成報告並退出。
-
{ "Comment": "Runs specific groups if the test runner chose to do that, otherwise runs GroupA.", "StartAt": "SpecificGroupsCheck", "States": { "SpecificGroupsCheck": { "Type": "Choice", "Default": "RunGroupA", "FallthroughOnError": true, "Choices": [ { "Expression": "{{$.specificTestGroups[0]}} != ''", "Next": "RunSpecificGroups" } ] }, "RunSpecificGroups": { "Type": "RunTask", "Next": "Report", "Catch": [ { "ErrorEquals": [ "RunTaskError" ], "Next": "Fail" } ] }, "RunGroupA": { "Type": "RunTask", "Next": "Report", "TestGroup": "GroupA", "Catch": [ { "ErrorEquals": [ "RunTaskError" ], "Next": "Fail" } ] }, "Report": { "Type": "Report", "Next": "Succeed", "Catch": [ { "ErrorEquals": [ "ReportError" ], "Next": "Fail" } ] }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }
範例狀態機器:運行具有產品功能的單個測試組
此狀態機器:
-
執行測試組
GroupA
。 -
檢查執行錯誤和過渡到
Fail
(如果找到任何)。 -
新增
FeatureThatDependsOnGroupA
功能awsiotdevicetester_report.xml
文件:-
如果
GroupA
通道時,要素會設定為supported
。 -
該功能在報告中未標記為可選。
-
-
生成報告並過渡到
Succeed
如果沒有錯誤,Fail
否則
{ "Comment": "Runs GroupA and adds product features based on GroupA", "StartAt": "RunGroupA", "States": { "RunGroupA": { "Type": "RunTask", "Next": "AddProductFeatures", "TestGroup": "GroupA", "ResultVar": "GroupA_passed", "Catch": [ { "ErrorEquals": [ "RunTaskError" ], "Next": "Fail" } ] }, "AddProductFeatures": { "Type": "AddProductFeatures", "Next": "Report", "Features": [ { "Feature": "FeatureThatDependsOnGroupA", "Groups": [ "GroupA" ], "IsRequired": true } ] }, "Report": { "Type": "Report", "Next": "Succeed", "Catch": [ { "ErrorEquals": [ "ReportError" ], "Next": "Fail" } ] }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }
範例狀態機器:parallel 行運行兩個測試組
此狀態機器:
-
執行
GroupA
和GroupB
測試組並 parallel。所以此ResultVar
變量存儲在上下文中的RunTask
狀態可用於AddProductFeatures
狀態。 -
檢查執行錯誤和過渡到
Fail
(如果找到任何)。此狀態機不使用Catch
塊,因為該方法不檢測分支狀態計算機中的執行錯誤。 -
將要素添加到
awsiotdevicetester_report.xml
文件基於傳遞-
如果
GroupA
通道時,要素會設定為supported
。 -
該功能在報告中未標記為可選。
-
-
生成報告並過渡到
Succeed
如果沒有錯誤,Fail
否則
如果在設備池中配置了兩個設備,則GroupA
和GroupB
可以同時執行。但是,如果GroupA
或者GroupB
有多個測試,那麼兩個設備都可以分配給這些測試。如果只配置了一個設備,測試組將按順序運行。
{ "Comment": "Runs GroupA and GroupB in parallel", "StartAt": "RunGroupAAndB", "States": { "RunGroupAAndB": { "Type": "Parallel", "Next": "CheckForErrors", "Branches": [ { "Comment": "Run GroupA state machine", "StartAt": "RunGroupA", "States": { "RunGroupA": { "Type": "RunTask", "Next": "Succeed", "TestGroup": "GroupA", "ResultVar": "GroupA_passed", "Catch": [ { "ErrorEquals": [ "RunTaskError" ], "Next": "Fail" } ] }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }, { "Comment": "Run GroupB state machine", "StartAt": "RunGroupB", "States": { "RunGroupA": { "Type": "RunTask", "Next": "Succeed", "TestGroup": "GroupB", "ResultVar": "GroupB_passed", "Catch": [ { "ErrorEquals": [ "RunTaskError" ], "Next": "Fail" } ] }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } } ] }, "CheckForErrors": { "Type": "Choice", "Default": "AddProductFeatures", "FallthroughOnError": true, "Choices": [ { "Expression": "{{$.hasExecutionErrors}} == true", "Next": "Fail" } ] }, "AddProductFeatures": { "Type": "AddProductFeatures", "Next": "Report", "Features": [ { "Feature": "FeatureThatDependsOnGroupA", "Groups": [ "GroupA" ], "IsRequired": true }, { "Feature": "FeatureThatDependsOnGroupB", "Groups": [ "GroupB" ], "IsRequired": true } ] }, "Report": { "Type": "Report", "Next": "Succeed", "Catch": [ { "ErrorEquals": [ "ReportError" ], "Next": "Fail" } ] }, "Succeed": { "Type": "Succeed" }, "Fail": { "Type": "Fail" } } }