

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Konfigurasikan state machine IDT
<a name="idt-state-machine"></a>

**penting**  
Mulai IDT v4.5.1, mesin status ini tidak digunakan lagi. Kami sangat menyarankan Anda menggunakan orkestrator uji baru. Untuk informasi selengkapnya, lihat [Konfigurasikan orkestrator uji IDT](idt-test-orchestrator.md).

State machine adalah suatu konstruksi yang mengendalikan aliran eksekusi rangkaian uji. Ia menentukan keadaan awal dari rangkaian tes, mengelola transisi keadaan berdasarkan aturan yang ditetapkan pengguna, dan terus melakukan transisi melalui keadaan-keadaan tersebut sampai mencapai keadaan akhir. 

Jika rangkaian tes Anda tidak menyertakan state machine yang ditetapkan pengguna, IDT akan membuat state machine untuk Anda. State machine default melakukan fungsi-fungsi berikut:
+ Menyediakan test runner dengan kemampuan untuk memilih dan menjalankan grup uji tertentu, dan bukan seluruh rangkaian uji.
+ Jika grup uji tertentu tidak dipilih, ia menjalankan setiap grup uji di rangkaian uji dengan urutan acak. 
+ Membuat laporan dan mencetak ringkasan konsol yang menunjukkan hasil tes untuk setiap grup uji dan uji kasus.

State machine untuk rangkaian uji IDT harus memenuhi kriteria berikut:
+ Setiap keadaan sesuai dengan tindakan yang harus ddilakukan oleh IDT, seperti menjalankan grup uji atau produk file laporan.
+ Transisi ke suatu keadaan akan menghasilkan tindakan yang terkait dengan keadaan tersebut.
+ Setiap keadaan menentukan aturan transisi untuk keadaan berikutnya.
+ Keadaan akhir harus berupa `Succeed` atau `Fail`.

## Format state machine
<a name="state-machine-format"></a>

Anda dapat menggunakan templat berikut untuk mengonfigurasi file `<custom-test-suite-folder>/suite/state_machine.json` Anda: 

```
{
  "Comment": "<description>",
  "StartAt": "<state-name>",
  "States": {
    "<state-name>": {
      "Type": "<state-type>",
      // Additional state configuration
    }
    
    // Required states
    "Succeed": {
      "Type": "Succeed"
    },
    "Fail": {
      "Type": "Fail"
    }
  }
}
```

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Comment`  
Sebuah deskripsi tentang state machine.

`StartAt`  
Nama keadaan di mana IDT mulai menjalankan rangkaian tes. Nilai dari `StartAt` harus diatur ke salah satu keadaan yang tercantum di objek `States`.

`States`  
Sebuah objek yang memetakan nama keadaan yang ditetapkan pengguna ke keadaan IDT yang valid. Setiap Negara. *state-name*objek berisi definisi status valid yang dipetakan ke. *state-name*  
Objek `States` harus mencakup keadaan `Succeed` dan `Fail`. Untuk informasi lebih lanjut tentang keadaan yang valid, lihat [Keadaan yang valid dan definisi keadaan](#valid-states).

## Keadaan yang valid dan definisi keadaan
<a name="valid-states"></a>

Bagian ini menjelaskan definisi keadaan pada semua keadaan yang valid yang dapat digunakan dalam state machine IDT. Beberapa keadaan berikut mendukung konfigurasi pada tingkat uji kasus. Namun, kami sarankan Anda untuk mengonfigurasi aturan transisi keadaan pada tingkat grup uji dan bukan pada tingkat uji kasus kecuali jika benar-benar diperlukan.

**Topics**
+ [RunTask](#state-runtask)
+ [Pilihan](#state-choice)
+ [Paralel](#state-parallel)
+ [AddProductFeatures](#state-addproductfeatures)
+ [Laporan](#state-report)
+ [LogMessage](#state-logmessage)
+ [SelectGroup](#state-selectgroup)
+ [Gagal](#state-fail)
+ [Berhasil](#state-succeed)

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

Keadaan `RunTask` menjalankan uji kasus dari grup uji yang ditentukan dalam rangkaian tes.

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

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Next`  
Nama keadaan yang akan ditransisi setelah melaksanakan tindakan dalam keadaan saat ini.

`TestGroup`  
Tidak wajib. ID grup uji yang akan dijalankan. Jika nilai ini tidak ditentukan, IDT akan menjalankan grup uji yang dipilih oleh test runner.

`TestCases`  
Tidak wajib. Array kasus uji IDs dari grup yang ditentukan dalam`TestGroup`. Berdasarkan nilai-nilai `TestGroup` dan `TestCases`, IDT menentukan perilaku eksekusi tes sebagai berikut:   
+ Ketika `TestGroup` dan `TestCases` ditentukan, IDT akan menjalankan uji kasus tertentu dari grup uji. 
+ Ketika `TestCases` ditentukan tetapi `TestGroup` tidak ditentukan, IDT akan menjalankan uji kasus yang ditentukan.
+ Ketika `TestGroup` ditentukan tetapi `TestCases` tidak ditentukan, IDT akan menjalankan semua uji kasus di grup uji yang ditentukan.
+ Ketika `TestGroup` ataupun `TestCases` tidak ditentukan, IDT akan menjalankan semua uji kasus dari grup uji yang dipilih oleh test runner dari IDT CLI. Untuk mengaktifkan pilihan grup untuk test runner, Anda harus menyertakan keadaan `RunTask` dan `Choice` dalam file `state_machine.json` Anda. Untuk contoh cara kerjanya, lihat [Contoh state machine: Jalankan grup uji yang dipilih pengguna](#allow-specific-groups).

  Untuk informasi selengkapnya tentang mengaktifkan perintah IDT CLI untuk test runner, lihat [Aktifkan perintah IDT CLI](create-test-executables.md#idt-cli-coop).

`ResultVar`  
Nama variabel konteks yang akan diatur dengan hasil uji yang dijalankan. Jangan tentukan nilai ini jika Anda tidak menentukan nilai untuk `TestGroup`. IDT menetapkan nilai variabel yang Anda tentukan di `ResultVar` hingga `true` atau `false` berdasarkan berikut ini:   
+ Jika nama variabel adalah dari bentuk `text_text_passed`, maka nilainya akan diatur ke apakah semua tes dalam grup uji pertama akan dilalui atau dilompati.
+ Dalam semua kasus lainnya, nilai akan diatur ke apakah semua tes di semua grup uji akan dilalui atau dilompati.

Biasanya, Anda akan menggunakan `RunTask` status untuk menentukan ID grup uji tanpa menentukan kasus uji individual IDs, sehingga IDT akan menjalankan semua kasus uji dalam kelompok uji yang ditentukan. Semua uji kasus yang dijalankan oleh keadaan ini berjalan secara paralel, dengan urutan acak. Namun, jika semua uji kasus memerlukan perangkat untuk dijalankan, dan hanya satu perangkat yang tersedia, maka uji kasus akan berjalan secara berurutan sebagai gantinya. 

**Penanganan kesalahan**

Jika salah satu grup uji atau kasus uji IDs yang ditentukan tidak valid, maka status ini mengeluarkan kesalahan `RunTaskError` eksekusi. Jika keadaan ini menemukan kesalahan eksekusi, ia juga akan menetapkan variabel `hasExecutionError` dalam konteks state machine ke `true`.

### Pilihan
<a name="state-choice"></a>

Keadaan `Choice` memungkinkan Anda secara dinamis mengatur keadaan berikutnya yang akan ditransisikan berdasarkan keadaan yang ditetapkan pengguna.

```
{
    "Type": "Choice",
    "Default": "<state-name>", 
    "FallthroughOnError": true | false,
    "Choices": [
        {
            "Expression": "<expression>",
            "Next": "<state-name>"
        }
    ]
}
```

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Default`  
Keadaan default yang akan ditransisikan jika tidak terdapat ekspresi yang ditentukan di `Choices` dapat dievaluasi pada `true`.

`FallthroughOnError`  
Tidak wajib. Menentukan perilaku ketika keadaan tersebut bertemu kesalahan dalam mengevaluasi ekspresi. Atur ke `true` jika Anda ingin melompati ekspresi jika hasil evaluasi menghasilkan kesalahan. Jika tidak ada ekspresi yang cocok, state machine akan bertransisi ke keadaan `Default`. Jika nilai `FallthroughOnError` tidak ditentukan, default-nya adalah `false`. 

`Choices`  
Serangkaian ekspresi dan keadaan untuk menentukan keadaan mana yang akan ditransisikan setelah mengeksekusi tindakan dalam keadaan saat ini.    
`Choices.Expression`  
Ekspresi yang harus dievaluasi pada nilai boolean. Jika ekspresi mengevaluasi `true`, maka state machine akan bertransisi ke keadaan yang ditentukan dalam `Choices.Next`. String ekspresi mengambil nilai-nilai dari konteks state machine dan kemudian melakukan operasi padanya untuk sampai pada nilai boolean. Untuk informasi tentang mengakses konteks state machine, lihat [Konteks mesin keadaan](#state-machine-context).   
`Choices.Next`  
Nama keadaan yang akan ditransisikan jika ekspresi yang ditentukan dalam `Choices.Expression` dievaluasi pada `true`.

**Penanganan kesalahan**

Keadaan `Choice` dapat memerlukan penanganan kesalahan dalam kasus berikut: 
+ Beberapa variabel dalam ekspresi pilihan tidak ada dalam konteks state machine.
+ Hasil ekspresi bukan merupakan nilai boolean.
+ Hasil pencarian JSON bukanlah string, nomor, atau boolean.

Anda tidak dapat menggunakan blok `Catch` untuk menangani kesalahan dalam keadaan ini. Jika Anda ingin berhenti mengeksekusi state machine ketika menemukan kesalahan, Anda harus mengatur `FallthroughOnError` ke `false`. Namun, kami menyarankan agar Anda mengatur `FallthroughOnError` ke `true` Anda, dan tergantung pada kasus penggunaan Anda, lakukan salah satu langkah berikut:
+ Jika variabel yang Anda akses diharapkan untuk tidak ada dalam beberapa kasus, gunakan nilai `Default` dan blok `Choices` tambahan untuk menentukan keadaan berikutnya.
+ Jika variabel yang Anda akses harus selalu ada, atur keadaan `Default`ke `Fail`.

### Paralel
<a name="state-parallel"></a>

Keadaan `Parallel` memungkinkan Anda untuk menentukan dan menjalankan state machine baru secara paralel satu sama lain.

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

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Next`  
Nama keadaan yang akan ditransisi setelah melaksanakan tindakan dalam keadaan saat ini.

`Branches`  
Serangkaian definisi state machine yang akan dijalankan. Setiap definisi state machine harus berisi keadaan `StartAt`, `Succeed`, dan `Fail` miliknya sendiri. Definisi state machine dalam rangkaian ini tidak dapat mengacu pada keadaan di luar definisinya sendiri.   
Karena setiap cabang state machine memiliki konteks state machine yang sama, pengaturan variabel dalam satu cabang dan kemudian pembacaan variabel-variabel dari cabang lain dapat mengakibatkan perilaku yang tidak terduga.

Keadaan `Parallel` bergerak ke keadaan berikutnya hanya setelah keadaan tersebut menjalankan semua cabang state machine. Setiap keadaan yang memerlukan perangkat akan menunggu untuk berjalan hingga perangkat tersebut tersedia. Jika beberapa perangkat tersedia, keadaan ini akan menjalankan uji kasus dari beberapa grup secara paralel. Jika tidak tersedia perangkat yang memadai, uji kasus akan berjalan secara berurutan. Karena uji kasus dijalankan dalam urutan acak ketika berjalan secara paralel, perangkat yang berbeda mungkin digunakan untuk menjalankan tes dari grup tes yang sama. 

**Penanganan kesalahan**

Pastikan bahwa baik state machine cabang dan state machine induk bertransisi ke keadaan `Fail` untuk menangani kesalahan eksekusi. 

Karena state machine cabang tidak mengirimkan kesalahan eksekusi ke state machine induk, Anda tidak dapat menggunakan blok `Catch` untuk menangani kesalahan eksekusi di state machine cabang. Sebagai gantinya, gunakan nilai `hasExecutionErrors` dalam konteks state machine bersama. Untuk contoh cara bekerjanya, lihat [Contoh state machine: Jalankan dua grup uji secara paralel](#run-in-parallel).

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

Keadaan `AddProductFeatures` memungkinkan Anda menambahkan fitur produk ke file `awsiotdevicetester_report.xml` yang dihasilkan oleh IDT. 

Fitur produk adalah informasi yang ditetapkan pengguna tentang kriteria spesifik yang mungkin dipenuhi oleh perangkat. Misalnya, fitur produk `MQTT` dapat menetapkan bahwa perangkat akan menerbitkan pesan MQTT dengan benar. Dalam laporan tersebut, fitur produk ditetapkan sebagai `supported`, `not-supported`, atau nilai kustom, berdasarkan apakah tes yang ditentukan berhasil dilalui.



**catatan**  
Keadaan `AddProductFeatures` tidak menghasilkan laporan dengan sendirinya. Keadaan ini harus bertransisi ke [keadaan `Report`](#state-report) untuk menghasilkan laporan.

```
{
    "Type": "Parallel",
    "Next": "<state-name>",
    "Features": [
        {
            "Feature": "<feature-name>", 
            "Groups": [
                "<group-id>"
            ],
            "OneOfGroups": [
                "<group-id>"
            ],
            "TestCases": [
                "<test-id>"
            ],
            "IsRequired": true | false,
            "ExecutionMethods": [
                "<execution-method>"
            ]
        }
    ]
}
```

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Next`  
Nama keadaan yang akan ditransisi setelah melaksanakan tindakan dalam keadaan saat ini.

`Features`  
Serangkaian fitur produk yang akan ditampilkan di file `awsiotdevicetester_report.xml`.    
`Feature`  
Nama fitur  
`FeatureValue`  
Tidak wajib. Nilai kustom yang akan digunakan dalam laporan, dan bukan `supported`. Jika nilai ini tidak ditentukan, maka berdasarkan hasil tes, nilai fitur akan diatur ke `supported` atau `not-supported`.   
Jika Anda menggunakan nilai kustom untuk `FeatureValue`, Anda dapat menguji fitur yang sama dengan kondisi yang berbeda, dan IDT akan menggabungkan nilai fitur untuk kondisi yang didukung. Misalnya, petikan berikut menunjukkan fitur `MyFeature` dengan dua nilai fitur yang terpisah:  

```
...
{
    "Feature": "MyFeature",
    "FeatureValue": "first-feature-supported",
    "Groups": ["first-feature-group"]
},
{
    "Feature": "MyFeature",
    "FeatureValue": "second-feature-supported",
    "Groups": ["second-feature-group"]
},
...
```
Jika kedua grup uji itu lulus, nilai fitur akan diatur ke `first-feature-supported, second-feature-supported`.   
`Groups`  
Tidak wajib. Array kelompok uji IDs. Semua tes dalam setiap kelompok uji yang ditentukan harus lulus pada fitur yang akan didukung.  
`OneOfGroups`  
Tidak wajib. Array kelompok uji IDs. Semua tes dalam setidaknya satu kelompok uji yang ditentukan harus lulus pada fitur yang akan didukung.   
`TestCases`  
Tidak wajib. Sebuah array kasus uji IDs. Jika Anda menentukan nilai ini, maka hal berikut ini akan berlaku:  
+ Semua uji kasus yang ditentukan harus lulus pada fitur yang akan didukung.
+ `Groups` harus berisi hanya satu ID grup uji.
+ `OneOfGroups` tidak boleh ditentukan.  
`IsRequired`  
Tidak wajib. Atur ke `false` untuk menandai fitur ini sebagai fitur opsional dalam laporan. Nilai default adalah `true`.  
`ExecutionMethods`  
Tidak wajib. Serangkaian metode eksekusi yang sesuai dengan nilai `protocol` yang ditentukan dalam file `device.json`. Jika nilai ini ditentukan, test runner harus menentukan nilai `protocol` yang cocok dengan salah satu nilai dalam rangkaian ini untuk menyertakan fitur tersebut dalam laporan. Jika nilai ini tidak ditentukan, maka fitur itu akan selalu disertakan dalam laporan.

Untuk menggunakan keadaan `AddProductFeatures`, Anda harus menetapkan nilai `ResultVar` di keadaan `RunTask` ke salah satu nilai berikut:
+ Jika Anda menentukan kasus uji individual IDs, maka atur `ResultVar` ke`group-id_test-id_passed`.
+ Jika Anda tidak menentukan kasus uji individual IDs, maka setel `ResultVar` ke`group-id_passed`.

Keadaan `AddProductFeatures` akan mengecek hasil tes dengan cara berikut: 
+ Jika Anda tidak menentukan kasus uji apa pun IDs, maka hasil untuk setiap kelompok uji ditentukan dari nilai `group-id_passed` variabel dalam konteks mesin negara.
+ Jika Anda memang menentukan kasus uji IDs, maka hasil untuk masing-masing pengujian ditentukan dari nilai `group-id_test-id_passed` variabel dalam konteks mesin negara.

**Penanganan kesalahan**

Jika ID grup yang disediakan dalam keadaan ini bukan ID grup yang valid, maka keadaan ini akan menghasilkan kesalahan eksekusi `AddProductFeaturesError`. Jika keadaan ini menemukan kesalahan eksekusi, ia juga akan menetapkan variabel `hasExecutionErrors` dalam konteks state machine ke `true`.

### Laporan
<a name="state-report"></a>

Keadaan `Report` menghasilkan file `suite-name_Report.xml` dan `awsiotdevicetester_report.xml`. Keadaan ini juga mengalirkan laporan ke konsol.

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

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Next`  
Nama keadaan yang akan ditransisi setelah melaksanakan tindakan dalam keadaan saat ini.

Anda harus selalu beralih ke keadaan `Report` menjelang akhir aliran eksekusi tes agar test runner dapat melihat hasil tes. Biasanya, keadaan berikutnya setelah keadaan ini adalah `Succeed`. 

**Penanganan kesalahan**

Jika keadaan ini mengalami masalah dalam menghasilkan laporan, keadaan tersebut akan mengeluarkan kesalahan eksekusi `ReportError`. 

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

Keadaan `LogMessage` akan menghasilkan file `test_manager.log` dan mengalirkan pesan log ke konsol.

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

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Next`  
Nama keadaan yang akan ditransisi setelah melaksanakan tindakan dalam keadaan saat ini.

`Level`  
Tingkat kesalahan tempat membuat pesan log. Jika Anda menentukan tingkat yang tidak valid, keadaan ini akan menghasilkan pesan kesalahan dan membuangnya. 

`Message`  
Pesan yang akan dicatat.

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

Keadaan `SelectGroup` memperbarui konteks state machine untuk menunjukkan grup mana yang dipilih. Nilai-nilai yang ditetapkan oleh keadaan ini digunakan oleh setiap kondisi `Choice` berikutnya.

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

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Next`  
Nama keadaan yang akan ditransisi setelah melaksanakan tindakan dalam keadaan saat ini.

`TestGroups`  
Serangkaian grup uji yang akan ditandai sudah dipilih. Untuk setiap ID grup uji dalam rangkaian ini, variabel `group-id_selected` akan diatur ke `true` dalam konteks. Pastikan Anda menyediakan grup pengujian yang valid IDs karena IDT tidak memvalidasi apakah grup yang ditentukan ada.

### Gagal
<a name="state-fail"></a>

Keadaan `Fail` menunjukkan bahwa state machine tidak mengeksekusi dengan benar. Ini adalah keadaan akhir untuk state machine, dan setiap definisi state machine harus mencakup keadaan ini.

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

### Berhasil
<a name="state-succeed"></a>

Keadaan `Succeed` menunjukkan bahwa state machine mengeksekusi dengan benar. Ini adalah keadaan akhir untuk state machine, dan setiap definisi state machine harus mencakup keadaan ini.

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

## Konteks mesin keadaan
<a name="state-machine-context"></a>

Konteks state machine adalah dokumen JSON baca-saja yang berisi data yang tersedia untuk state machine selama eksekusi. Konteks state machine hanya dapat diakses dari state machine, dan berisi informasi yang menentukan aliran uji. Misalnya, Anda dapat menggunakan informasi yang dikonfigurasi oleh test runner di file `userdata.json` untuk menentukan apakah pengujian tertentu wajib dijalankan.

Konteks state machine menggunakan format berikut:

```
{
    "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`  
Informasi tentang kolam perangkat yang dipilih untuk uji coba. Untuk kolam perangkat yang dipilih, informasi ini diambil dari elemen rangkaian perangkat tingkat atas yang sesuai yang ditentukan dalam file `device.json`.

`userData`  
Informasi di file `userdata.json`.

`config`  
Informasi menyematkan file `config.json`.

`suiteFailed`  
Nilai diatur ke `false` ketika state machine dimulai. Jika grup uji gagal dalam keadaan `RunTask`, maka nilai ini akan ditetapkan ke `true` untuk durasi sisa eksekusi state machine.

`specificTestGroups`  
Jika test runner memilih grup pengujian tertentu untuk dijalankan, bukan seluruh rangkaian pengujian, kunci ini dibuat dan berisi daftar grup pengujian tertentu. IDs

`specificTestCases`  
Jika test runner memilih kasus pengujian tertentu untuk dijalankan, bukan seluruh rangkaian pengujian, kunci ini dibuat dan berisi daftar kasus uji tertentu. IDs

`hasExecutionErrors`  
Tidak keluar saat state machine dimulai. Jika keadaan apa pun menemukan kesalahan eksekusi, variabel ini akan dibuat dan diatur ke `true` selama durasi sisa eksekusi state machine.

Anda dapat menanyakan konteks menggunakan JSONPath notasi. Sintaks untuk JSONPath kueri dalam definisi negara adalah. `{{$.query}}` Anda dapat menggunakan JSONPath kueri sebagai string placeholder di beberapa negara bagian. IDT menggantikan string placeholder dengan nilai kueri yang dievaluasi JSONPath dari konteks. Anda dapat menggunakan placeholder untuk nilai-nilai berikut:
+ Nilai `TestCases` dalam keadaan `RunTask`. 
+ Nilai `Expression` keadaan `Choice`.

Ketika Anda mengakses data dari konteks state machine, pastikan keadaan berikut dipenuhi: 
+ Jalur JSON Anda harus dimulai dengan `$.`
+ Setiap nilai harus dievaluasi pada string, angka, atau boolean.

Untuk informasi selengkapnya tentang penggunaan JSONPath notasi untuk mengakses data dari konteks, lihat[Gunakan konteks IDT](idt-context.md).

## Kesalahan eksekusi
<a name="execution-errors"></a>

Kesalahan eksekusi adalah kesalahan dalam definisi state machine yang ditemui oleh state machine mesin ketika mengeksekusi keadaan. IDT mencatat informasi tentang setiap kesalahan dalam file `test_manager.log` dan mengalirkan pesan log ke konsol.

Anda dapat menggunakan metode berikut untuk menangani kesalahan eksekusi:
+ Tambahkan [blok `Catch`](#catch) dalam definisi keadaan.
+ Periksa nilai dari [nilai `hasExecutionErrors`](#context) dalam konteks state machine.

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

Untuk menggunakan `Catch`, tambahkan hal berikut ini ke definisi keadaan Anda:

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

Semua kolom yang berisi nilai wajib diisi seperti yang dijelaskan di sini:

`Catch.ErrorEquals`  
Serangkaian jenis kesalahan yang akan ditangkap. Jika kesalahan eksekusi cocok dengan salah satu nilai yang ditentukan, maka state machine akan bertransisi ke keadaan yang ditentukan dalam `Catch.Next`. Lihat setiap definisi keadaan untuk informasi tentang jenis kesalahan yang dihasilkannya.

`Catch.Next`  
Keadaan berikutnya yang akan ditransisikan jika keadaan saat ini menemukan kesalahan eksekusi yang cocok dengan salah satu nilai yang ditentukan dalam `Catch.ErrorEquals`.

Blok tangkapan ditangani secara berurutan hingga salah satunya cocok. Jika tidak ada kesalahan yang cocok dengan yang tercantum dalam blok Tangkapan, maka state machine akan terus mengeksekusi. Karena kesalahan eksekusi adalah akibat dari definisi keadaan yang salah, kami sarankan Anda beralih ke keadaan gagal ketika suatu keadaan mengalami kesalahan eksekusi.

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

Ketika beberapa keadaan mengalami kesalahan eksekusi, selain mengeluarkan kesalahan, keaadaan itu juga mengatur nilai `hasExecutionError` ke `true` dalam konteks state machine. Anda dapat menggunakan nilai ini untuk mendeteksi ketika terjadi kesalahan, dan kemudian menggunakan keadaan `Choice` untuk mengalihkan state machine ke keadaan `Fail`.

Metode ini memiliki karakteristik sebagai berikut.
+ State machine tidak dimulai dengan nilai yang ditugaskan pada `hasExecutionError`, dan nilai ini tidak tersedia sampai keadaan tertentu menetapkannya. Ini berarti bahwa Anda harus secara tegas mengatur `FallthroughOnError` ke `false` untuk keadaan `Choice` yang mengakses nilai ini untuk mencegah state machine berhenti jika tidak ada kesalahan eksekusi yang terjadi. 
+ Setelah ditetapkan ke `true`, `hasExecutionError` tidak pernah ditetapkan menjadi salah atau dihapus dari konteks. Ini berarti bahwa nilai ini berguna hanya pertama kalinya ketika nilai tersebut ditetapkan ke `true`, dan untuk semua keadaan berikutnya, nilai itu tidak memberikan nilai yang berarti.
+ Nilai `hasExecutionError` dibagi dengan semua cabang state machine pada keadaan `Parallel`, yang dapat mengakibatkan hasil yang tidak diharapkan tergantung pada urutan yang diakses.

Karena karakteristik ini, kami tidak menyarankan Anda menggunakan metode ini jika Anda dapat menggunakan blok Catch sebagai gantinya. 

## Contoh mesin keadaan
<a name="state-machine-examples"></a>

Bagian ini menyediakan beberapa contoh konfigurasi state machine.

**Topics**
+ [Contoh state machine: Jalankan grup uji tunggal](#single-test-group)
+ [State machine contoh: Jalankan grup uji yang dipilih pengguna](#allow-specific-groups)
+ [Contoh state machine: Jalankan grup uji tunggal dengan fitur produk](#run-with-product-features)
+ [Contoh state machine: Jalankan dua grup uji secara paralel](#run-in-parallel)

### Contoh state machine: Jalankan grup uji tunggal
<a name="single-test-group"></a>

State machine ini:
+ Menjalankan grup uji dengan id `GroupA`, yang harus ada dalam rangkaian pada file `group.json`.
+ Memeriksa kesalahan eksekusi dan bertransisi ke `Fail` jika ada yang ditemukan.
+ Menghasilkan laporan dan bertransisi ke `Succeed` jika tidak ada kesalahan, dan `Fail` bila sebaliknya.

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

### State machine contoh: Jalankan grup uji yang dipilih pengguna
<a name="allow-specific-groups"></a>

State machine ini:
+ Memeriksa apakah test runner telah memilih grup uji tertentu. State machine tidak memeriksa uji kasus tertentu karena test runner tidak dapat memilih uji kasus tanpa sekaligus memilih grup uji.
+ Jika grup uji sudah dipilih: 
  + Jalankan uji kasus dalam grup uji yang dipilih. Untuk melakukannya, state machine tidak secara tegas menentukan grup uji atau uji kasus di keadaan `RunTask`
  + Buat laporan setelah menjalankan semua tes dan keluar.
+ Jika grup uji tidak dipilih:
  + Jalankan tes dalam grup uji `GroupA`.
  + Buat laporan dan keluar.

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

### Contoh state machine: Jalankan grup uji tunggal dengan fitur produk
<a name="run-with-product-features"></a>

State machine ini:
+ Menjalankan grup uji `GroupA`.
+ Memeriksa kesalahan eksekusi dan bertransisi ke `Fail` jika ada yang ditemukan.
+ Menambahkan fitur `FeatureThatDependsOnGroupA` pada file `awsiotdevicetester_report.xml`:
  + Jika `GroupA` lulus, fitur tersebut diatur ke `supported`.
  + Fitur ini tidak ditandai opsional dalam laporan.
+ Menghasilkan laporan dan bertransisi ke `Succeed` jika tidak ada kesalahan, dan `Fail` bila sebaliknya.

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

### Contoh state machine: Jalankan dua grup uji secara paralel
<a name="run-in-parallel"></a>

State machine ini:
+ Menjalankan grup tes `GroupA` dan `GroupB` secara paralel. Variabel `ResultVar` yang disimpan dalam konteks tersebut oleh keadaan `RunTask` dalam state machine cabang yang tersedia pada keadaan `AddProductFeatures`
+ Memeriksa kesalahan eksekusi dan bertransisi ke `Fail` jika ada yang ditemukan. State machine ini tidak menggunakan blok `Catch` karena metode itu tidak mendeteksi kesalahan eksekusi di state machine cabang.
+ Menambahkan fitur ke file `awsiotdevicetester_report.xml` berdasarkan grup-grup yang lulus
  + Jika `GroupA` lulus, fitur tersebut diatur ke `supported`.
  + Fitur ini tidak ditandai opsional dalam laporan.
+ Menghasilkan laporan dan bertransisi ke `Succeed` jika tidak ada kesalahan, dan `Fail` bila sebaliknya.

Jika dua perangkat dikonfigurasi di kolam perangkat, baik `GroupA` maupun `GroupB` dapat berjalan pada saat yang sama. Namun, jika `GroupA` atau `GroupB` memiliki beberapa tes di dalamnya, maka kedua perangkat dapat dialokasikan pada tes tersebut. Jika hanya satu perangkat yang dikonfigurasi, grup uji akan berjalan secara berurutan.

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