

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# IDT ステートマシンを設定する
<a name="idt-state-machine"></a>

**重要**  
IDT v4.5.1 以降、このステートマシンは非推奨です。新しいテストオーケストレーターを使用することを強くお勧めします。詳細については、「[IDT テストオーケストレーターを設定する](idt-test-orchestrator.md)」を参照してください。

ステートマシンは、テストスイートの実行フローを制御するコンストラクトです。テストスイートの開始ステートを決定し、ユーザー定義のルールに基づいてステートの移行を管理し、終了ステートに達するまでステートの移行を継続します。

テストスイートにユーザー定義のステートマシンが含まれていない場合は、IDT によってステートマシンが生成されます。デフォルトのステートマシンには、次の機能があります。
+ テストの実行者に、テストスイート全体ではなく、特定のテストグループを選択して実行する機能を提供する。
+ 特定のテストグループが選択されていない場合、テストスイート内のすべてのテストグループをランダムな順序で実行する。
+ レポートを生成し、各テストグループおよびテストケースのテスト結果を示すコンソールサマリーを出力する。

IDT テストスイートのステートマシンは、次の基準を満たす必要があります。
+ 各ステートが、IDT が実行する各アクション (テストグループの実行、レポートファイルの生成など) に対応する。
+ ステートが移行すると、そのステートに関連付けられたアクションを実行する。
+ 各ステートが、次のステートの移行ルールを定義する。
+ 終了ステートが `Succeed` または `Fail` である。

## ステートマシンの形式
<a name="state-machine-format"></a>

次のテンプレートを使用して、独自の `<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.*state-name* オブジェクトには、*state-name* にマッピングされた有効なステートの定義が含まれています。  
`States` オブジェクトには、`Succeed` ステートおよび `Fail` ステートを含める必要があります。有効なステートについては、[有効なステートとステートの定義](#valid-states)を参照してください。

## 有効なステートとステートの定義
<a name="valid-states"></a>

このセクションでは、IDT ステートマシンで使用可能なすべての有効なステートのステート定義について説明します。以下に示すステートの一部は、テストケースレベルでの設定をサポートしています。ただし、絶対に必要な場合を除き、テストケースレベルではなく、テストグループレベルでステート移行ルールを設定することをお勧めします。

**Topics**
+ [RunTask](#state-runtask)
+ [選択](#state-choice)
+ [並行](#state-parallel)
+ [AddProductFeatures](#state-addproductfeatures)
+ [レポートを行う](#state-report)
+ [LogMessage](#state-logmessage)
+ [SelectGroup](#state-selectgroup)
+ [失敗](#state-fail)
+ [成功](#state-succeed)

### RunTask
<a name="state-runtask"></a>

`RunTask` ステートは、テストスイートで定義されているテストグループからテストケースを実行します。

```
{
    "Type": "RunTask",
    "Next": "<state-name>",
    "TestGroup": "<group-id>",
    "TestCases": [
        "<test-id>"
    ],
    "ResultVar": "<result-name>"
}
```

以下に説明するように、値が含まれているすべてのフィールドは必須です。

`Next`  
現在のステートのアクションを実行した後に移行するステートの名前。

`TestGroup`  
オプション。実行するテストグループの ID。この値を指定しない場合、IDT はテストの実行者が選択するテストグループを実行します。

`TestCases`  
オプション。`TestGroup` に指定されたグループのテストケース ID の配列。IDT は、`TestGroup` と `TestCases` の値に基づいて、次のようにテストの実行動作を決定します。  
+ `TestGroup` と `TestCases` 両方が指定されている場合、IDT はテストグループから指定されたテストケースを実行します。
+ `TestCases` が指定され、`TestGroup` が指定されていない場合、IDT は指定されたテストケースを実行します。
+ `TestGroup` が指定され、`TestCases` が指定されていない場合は、IDT は指定されたテストグループ内のすべてのテストケースを実行します。
+ `TestGroup` も `TestCases` も指定されていない場合、IDT は、テストの実行者が IDT CLI から選択したテストグループからすべてのテストケースを実行します。テストの実行者がグループを選択できるようにするには、`state_machine.json` ファイルに `RunTask` ステートと `Choice`ステート両方を含める必要があります。これを行う方法の例については、[ステートマシンの例: ユーザーが選択したテストグループを実行する](#allow-specific-groups)を参照してください。

  テストの実行者向けの IDT CLI コマンドを有効にする方法については「[IDT CLI コマンドを有効にする](create-test-executables.md#idt-cli-coop)」を参照してください。

`ResultVar`  
テスト実行の結果によって設定するコンテキスト変数の名前。`TestGroup` の値を指定しなかった場合は、この値を指定しないでください。IDT は、以下に基づいて、`ResultVar` に定義された変数を `true` または `false` に設定します。  
+ 変数名の形式が `text_text_passed` の場合、この値は、最初のテストグループのすべてのテストが合格したか、スキップされたかに設定されます。
+ それ以外の場合、この値は、すべてのテストグループのすべてのテストが合格したか、スキップされたかに設定されます。

通常、`RunTask` ステートは、個々のテストケース ID を指定せずにテストグループ ID を指定するために使用されます。この指定により、IDT は指定されたテストグループ内のすべてのテストケースを実行します。このステートで実行されるすべてのテストケースは、ランダムな順序で並行して実行されます。ただし、すべてのテストケースが実行に 1 つのデバイスを必要とし、単一のデバイスしか使用できない場合は、テストケースは順次実行されます。

**エラー処理**

指定されたテストグループ ID またはテストケース ID のいずれかが有効でない場合、このステートは `RunTaskError` 実行エラーを発行します。またこのステートは、実行エラーに遭遇すると、ステートマシンコンテキスト内の `hasExecutionError` 変数を `true` に設定します。

### 選択
<a name="state-choice"></a>

`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` に定義されているステートに移行します。式文字列は、ステートマシンコンテキストから値を取得し、オペレーションを実行してブール値に到達します。ステートマシンコンテキストへのアクセスについては、「[ステートマシンコンテキスト](#state-machine-context)」を参照してください。  
`Choices.Next`  
`Choices.Expression` で定義されている式が `true` に評価された場合の移行先のステート名。

**エラー処理**

以下に示すケースでは、`Choice` ステートでエラー処理が必要になることがあります。
+ choice 式の一部の変数が、ステートマシンのコンテキストに存在しない。
+ 式の結果がブール値ではない。
+ JSON 検索の結果が、文字列、数値、またはブール値ではない。

このステートのエラー処理に `Catch` ブロックを使用することはできません。ステートマシンがエラーに遭遇したときに、その実行を停止するには、`FallthroughOnError` を `false` に設定する必要があります。ただし、`FallthroughOnError` は `true` に設定し、ユースケースに応じて、次のいずれかの操作を実行することをお勧めします。
+ アクセスしている変数が一部のケースに存在しないと考えられる場合は、`Default` の値と追加の `Choices` ブロックを使用して次のステートを指定します。
+ 使用している変数が必ず存在するものである場合は、`Default` ステートを `Fail` に設定します。

### 並行
<a name="state-parallel"></a>

`Parallel` ステートでは、新しいステートマシンを互いに並列に定義して実行できます。

```
{
    "Type": "Parallel",
    "Next": "<state-name>",
    "Branches": [
        <state-machine-definition>
    ]
}
```

以下に説明するように、値が含まれているすべてのフィールドは必須です。

`Next`  
現在のステートのアクションを実行した後に移行するステートの名前。

`Branches`  
実行するステートマシン定義の配列。各ステートマシン定義には、それぞれの `StartAt`、`Succeed`、および `Fail` ステートを含める必要があります。この配列内のステートマシン定義は、各自の定義外のステートを参照することはできません。  
各ブランチステートマシンは同じステートマシンコンテキストを共有するため、あるブランチに変数を設定し、別のブランチからそれらの変数を読み込むと、予期しない動作が発生する可能性があります。

`Parallel` ステートは、すべてのブランチステートマシンを実行してから次のステートに移行します。デバイスを必要とする各ステートは、デバイスが利用可能になるまで実行を待ちます。複数のデバイスが利用可能な場合、このステートは並行して複数のグループからテストケースを実行します。十分な数のデバイスが利用できない場合、テストケースは順次実行されます。テストケースは、並列して実行される場合、ランダムな順序で実行されるため、同じテストグループからのテストの実行に異なるデバイスが使用されることがあります。

**エラー処理**

実行エラーを処理するには、ブランチステートマシンと親ステートマシンの両方が、`Fail` ステートに移行していることを確認します。

ブランチステートマシンは親ステートマシンに実行エラーを送信しないため、ブランチステートマシンの実行エラーを処理するために `Catch` ブロックを使用することはできません。代わりに、共有ステートマシンコンテキストの `hasExecutionErrors` 値を使用します。これを行う方法の例については、[ステートマシンの例: 2 つのテストグループを並行して実行する](#run-in-parallel)を参照してください。

### AddProductFeatures
<a name="state-addproductfeatures"></a>

`AddProductFeatures` ステートでは、IDT によって生成される `awsiotdevicetester_report.xml` ファイルに製品機能を追加できます。

製品機能とは、デバイスが満たしている可能性のある特定の基準に関するユーザー定義の情報です。例えば、`MQTT` 製品機能には、デバイスが MQTT メッセージを適切に公開することを指定できます。レポートでは、製品機能は指定されたテストが合格したかどうかに応じて、`supported`、`not-supported`、カスタム値に設定されます。



**注記**  
`AddProductFeatures` ステートだけではレポートは生成されません。レポートを生成するには、このステートが [`Report` ステート](#state-report)に移行する必要があります。

```
{
    "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` ファイルに表示される製品機能の配列。    
`Feature`  
機能の名前。  
`FeatureValue`  
オプション。`supported` の代わりにレポートで使用するカスタム値。この値を指定しない場合、テスト結果に基づいて、機能値は `supported` または `not-supported` に設定されます。  
`FeatureValue` にカスタム値を使用する場合は、同じ機能を異なる条件でテストできます。IDT は、サポート条件の機能値を連結します。例えば、以下の抜粋は、`MyFeature` 機能と 2 つの異なる機能値を示しています。  

```
...
{
    "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 の配列。機能をサポートするには、指定されたテストグループうち、少なくとも 1 つのグループに含まれるすべてのテストが合格である必要があります。  
`TestCases`  
オプション。テストケース ID の配列。この値を指定すると、次のことが適用されます。  
+ 機能をサポートするには、指定されたすべてのテストケースが合格である必要があります。
+ `Groups` には、テストグループ ID を 1 つだけ含める必要があります。
+ `OneOfGroups` は指定できません。  
`IsRequired`  
オプション。この機能をレポートでオプション機能としてマークするには、`false` に設定します。デフォルト値は `true` です。  
`ExecutionMethods`  
オプション。`device.json` ファイルに指定された `protocol` 値と一致する実行メソッドの配列。この値を指定した場合、この機能をレポートに含めるには、テストの実行者はこの配列の値の 1 つに一致する `protocol` 値を指定する必要があります。この値を指定しない場合、この機能は常にレポートに含まれます。

`AddProductFeatures` ステートを使用するには、`RunTask` ステートの `ResultVar` の値を以下のいずれかの値に指定する必要があります。
+ 個々のテストケース 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` に設定します。

### レポートを行う
<a name="state-report"></a>

`Report` ステートでは、`suite-name_Report.xml` ファイルと `awsiotdevicetester_report.xml` ファイルが生成されます。またこのステートでは、レポートがコンソールにストリーミングされます。

```
{
    "Type": "Report",
    "Next": "<state-name>"
}
```

以下に説明するように、値が含まれているすべてのフィールドは必須です。

`Next`  
現在のステートのアクションを実行した後に移行するステートの名前。

テストの実行者がテスト結果を確認できるように、テスト実行フローの終了ステートの前に `Report` ステートに移行する必要があります。通常、このステートの次のステートは `Succeed` です。

**エラー処理**

このステートは、レポート生成時に問題に遭遇した場合、`ReportError` 実行エラーを発行します。

### LogMessage
<a name="state-logmessage"></a>

`LogMessage` ステートでは、`test_manager.log` ファイルが生成され、ログメッセージがコンソールにストリーミングされます。

```
{
    "Type": "LogMessage",
    "Next": "<state-name>"
    "Level": "info | warn | error"
    "Message": "<message>"
}
```

以下に説明するように、値が含まれているすべてのフィールドは必須です。

`Next`  
現在のステートのアクションを実行した後に移行するステートの名前。

`Level`  
ログメッセージを作成するエラーレベル。有効でないレベルを指定すると、エラーメッセージが生成され、そのレベルは破棄されます。

`Message`  
ログに記録するメッセージ。

### SelectGroup
<a name="state-selectgroup"></a>

`SelectGroup` ステートでは、ステートマシンコンテキストを更新して選択されたグループを示します。このステートで設定した値は、後続のすべての `Choice` ステートによって使用されます。

```
{
    "Type": "SelectGroup",
    "Next": "<state-name>"
    "TestGroups": [
        <group-id>"
    ]
}
```

以下に説明するように、値が含まれているすべてのフィールドは必須です。

`Next`  
現在のステートのアクションを実行した後に移行するステートの名前。

`TestGroups`  
選択済みとしてマークされるテストグループの配列。この配列の各テストグループ ID について、`group-id_selected` 変数がコンテキストで `true` に設定されます。IDT は、指定されたグループが存在するかどうかを検証しないため、有効なテストグループ ID を指定するようにしてください。

### 失敗
<a name="state-fail"></a>

`Fail` ステートは、ステートマシンが正しく実行されなかったことを示します。これはステートマシンの終了ステートです。各ステートマシンの定義にこのステートを含める必要があります。

```
{
    "Type": "Fail"
}
```

### 成功
<a name="state-succeed"></a>

`Succeed` ステートは、ステートマシンが正しく実行されたことを示します。これはステートマシンの終了ステートです。各ステートマシンの定義にこのステートを含める必要があります。

```
{
    "Type": "Succeed"
}
```

## ステートマシンコンテキスト
<a name="state-machine-context"></a>

ステートマシンコンテキストは、実行中のステートマシンに利用可能なデータが含まれている読み取り専用 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` ファイルで定義された、対応する最上位レベルのデバイスプール配列要素から取得されます。

`userData`  
`userdata.json` ファイル内の情報。

`config`  
`config.json` ファイル内の情報。

`suiteFailed`  
この値は、ステートマシンが起動すると `false` に設定されます。テストグループが `RunTask` ステートで失敗した場合、この値はステートマシン実行の残りの時間の間 `true` に設定されます。

`specificTestGroups`  
テストの実行者がテストスイート全体ではなく特定のテストグループを選択して実行する場合に、このキーが作成され、特定のテストグループ ID のリストが格納されます。

`specificTestCases`  
テストの実行者がテストスイート全体ではなく特定のテストケースを選択して実行する場合に、このキーが作成され、特定のテストケース ID のリストが格納されます。

`hasExecutionErrors`  
ステートマシンの起動時には存在しません。いずれかのステートが実行エラーに遭遇した場合に、この変数が作成され、ステートマシンの実行の残りの時間の間 `true` に設定されます。

コンテキストは、JSONPath 表記法を使用してクエリできます。ステート定義における JSonPath クエリの構文は `{{$.query}}` です。JSONPath クエリは、一部のステートではプレースホルダー文字列として使用できます。IDT は、プレースホルダー文字列をコンテキストから評価された JSONPath クエリの値に置き換えます。プレースホルダーは、次の値に使用できます。
+ `RunTask` ステートの `TestCases` 値。
+ `Choice` ステートの `Expression` 値。

ステートマシンコンテキストからデータにアクセスする場合は、次の条件を満たしていることを確認します。
+ JSON パスが `$.` で始まっている。
+ 各値が、文字列、数値、またはブール値として評価される。

JSONPath 表記を使用してコンテキストのデータにアクセスする方法の詳細については、[IDT コンテキストを使用する](idt-context.md)を参照してください。

## 実行エラー
<a name="execution-errors"></a>

実行エラーとは、ステートの実行時にステートマシンが遭遇する、ステートマシン定義内のエラーです。IDT は、各エラーに関する情報を `test_manager.log` ファイルに記録し、ログメッセージをコンソールにストリーミングします。

実行エラーは、次の方法を使用して処理できます。
+ ステート定義内に [`Catch`ブロック](#catch) を追加する。
+ ステートマシンコンテキストで [`hasExecutionErrors` 値](#context) の値を確認する。

### Catch
<a name="catch"></a>

`Catch` を使用するには、ステート定義に以下を追加します。

```
"Catch": [
    {    
        "ErrorEquals": [
            "<error-type>"
        ]
        "Next": "<state-name>" 
    }
]
```

以下に説明するように、値が含まれているすべてのフィールドは必須です。

`Catch.ErrorEquals`  
キャッチするエラータイプの配列。実行エラーが指定された値のいずれかと一致する場合、ステートマシンは、`Catch.Next` に指定されているステートに移行します。生成されるエラーのタイプの詳細については、各ステート定義を参照してください。

`Catch.Next`  
現在のステートが、`Catch.ErrorEquals` に指定されている値のいずれかと一致する実行エラーに遭遇した場合に、移行する次のステート。

キャッチブロックは、いずれかが一致するまで順番に処理されます。どのエラーもキャッチブロックに指定されているエラーと一致しない場合、ステートマシンは実行を継続します。実行エラーは誤ったステート定義によって発生するため、ステートが実行エラーに遭遇したときは Fail ステートに移行することをお勧めします。

### hasExecutionError
<a name="context"></a>

一部のステートは、実行エラーに遭遇した場合、エラーを発行するだけでなく、ステートマシンコンテキストの `hasExecutionError` 値も `true` に設定します。この値を使用して、エラーがいつ発生したかを特定してから、`Choice` ステートを使用してステートマシンを `Fail` ステートに移行することができます。

この方法には次の特徴があります。
+ ステートマシンは、`hasExecutionError` に値が割り当てられていると開始しません。またこの値は、特定のステートによって設定されるまで得られません。つまり、明示的に `FallthroughOnError` の値を `false` に設定することによって、実行エラーが発生していない場合に、この値にアクセスする `Choice` ステートがステートマシンを停止しないようにする必要があります。
+ `hasExecutionError` は、一度 `true` に設定されると、false に設定されることも、コンテキストから削除されることもありません。つまり、この値は `true` に設定された初回のみ有効であり、以降のすべてのステートに対して意味のある値を提供しないことを意味します。
+ `hasExecutionError` 値は `Parallel` ステート内のすべてのブランチステートマシンで共有されるため、アクセスされる順序によっては、予期せぬ結果が発生する可能性があります。

これらの特性から、代わりに Catch ブロックを使用できる場合は、この方法を使用することはお勧めしません。

## ステートマシンの例
<a name="state-machine-examples"></a>

このセクションでは、ステートマシンの設定の例を紹介します。

**Topics**
+ [ステートマシンの例: 1 つのテストグループを実行する](#single-test-group)
+ [ステートマシンの例: ユーザーが選択したテストグループを実行する](#allow-specific-groups)
+ [ステートマシンの例: 製品機能が含まれる 1 つのテストグループを実行する](#run-with-product-features)
+ [ステートマシンの例: 2 つのテストグループを並行して実行する](#run-in-parallel)

### ステートマシンの例: 1 つのテストグループを実行する
<a name="single-test-group"></a>

このステートマシンの動作:
+ ID `GroupA` のテストグループを実行します。このテストグループは、`group.json` ファイルのスイート内に存在している必要があります。
+ 実行エラーをチェックし、エラーが見つかった場合は `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"
        }
    }
}
```

### ステートマシンの例: ユーザーが選択したテストグループを実行する
<a name="allow-specific-groups"></a>

このステートマシンの動作:
+ テストの実行者が特定のテストグループを選択したかどうかをチェックします。テストの実行者がテストケースを選択するには、テストグループも選択する必要があるため、ステートマシンは特定のテストケースはチェックしません。
+ テストグループが選択されている場合: 
  + 選択されたテストグループ内のテストケースを実行します。そのために、ステートマシンは、`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"
        }
    }
}
```

### ステートマシンの例: 製品機能が含まれる 1 つのテストグループを実行する
<a name="run-with-product-features"></a>

このステートマシンの動作:
+ テストグループ `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"
        }
    }
}
```

### ステートマシンの例: 2 つのテストグループを並行して実行する
<a name="run-in-parallel"></a>

このステートマシンの動作:
+ `GroupA` および `GroupB` テストグループを並行して実行します。ブランチステートマシンの `RunTask` ステートによってコンテキストに格納された `ResultVar` 変数が `AddProductFeatures` ステートに利用可能になります。
+ 実行エラーをチェックし、エラーが見つかった場合は `Fail` に移行します。このステートマシンは、`Catch` ブロックを使用しません。この方法では、ブランチステートマシンの実行エラーが検出されないためです。
+ 合格したグループに基づいて、`awsiotdevicetester_report.xml` ファイルに機能を追加します。
  + `GroupA` が合格である場合、機能を `supported` に設定します。
  + レポートでこの機能をオプションとしてマークしません。
+ エラーがない場合には、レポートを生成し、`Succeed` に移行します。エラーがある場合は、`Fail` に移行します。

デバイスプールに 2 つのデバイスが設定されている場合、`GroupA` と `GroupB` 両方を同時に実行できます。ただし、`GroupA` または `GroupB` のどちらかに複数のテストが含まれている場合は、両方のデバイスがそれらのテストに割り当てられることがあります。デバイスが 1 つだけ設定されている場合、テストグループは順次実行されます。

```
{
    "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"
        }
    }
}
```