

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Configure la máquina de estados IDT
<a name="idt-state-machine"></a>

**importante**  
A partir de la versión 4.5.1 de IDT, esta máquina de estados está obsoleta. Le recomendamos encarecidamente que utilice el nuevo orquestador de pruebas. Para obtener más información, consulte [Configuración del orquestador de pruebas de IDT](idt-test-orchestrator.md).

Una máquina de estados es un constructo que controla el flujo de ejecución del conjunto de pruebas. Determina el estado inicial de un conjunto de pruebas, administra las transiciones de estado en función de las reglas definidas por el usuario y continúa pasando por esos estados hasta alcanzar el estado final. 

Si su conjunto de pruebas no incluye una máquina de estados definida por el usuario, IDT la generará. La máquina de estados predeterminada realiza las siguientes funciones:
+ Ofrece a los ejecutores de pruebas la posibilidad de seleccionar y ejecutar grupos de pruebas específicos, en lugar de todo el conjunto de pruebas.
+ Si no se seleccionan grupos de pruebas específicos, ejecuta todos los grupos de pruebas del conjunto de pruebas con asignación al azar. 
+ Genera informes e imprime un resumen de la consola que muestra los resultados de las pruebas de cada grupo y caso de prueba.

La máquina de estados de un conjunto de pruebas de IDT debe cumplir los siguientes criterios:
+ Cada estado corresponde a una acción que debe realizar IDT, como ejecutar un grupo de pruebas o crear un archivo de informe.
+ La transición a un estado ejecuta la acción asociada a ese estado.
+ Cada estado define la regla de transición para el siguiente estado.
+ El estado final debe ser `Succeed` o `Fail`.

## Formato de las máquinas de estados
<a name="state-machine-format"></a>

Puede utilizar la siguiente plantilla para configurar su propio archivo `<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"
    }
  }
}
```

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Comment`  
Una descripción de la máquina de estados.

`StartAt`  
El nombre del estado en el que IDT comienza a ejecutar el conjunto de pruebas. El valor de `StartAt` debe estar establecido en uno de los estados enumerados en el objeto `States`.

`States`  
Objeto que asigna los nombres de estado definidos por el usuario a estados de IDT válidos. Cada uno de los estados. *state-name*el objeto contiene la definición de un estado válido asignado a. *state-name*  
El objeto `States` debe incluir los estados `Succeed` y `Fail`. Para obtener información sobre los estados válidos, consulte [Estados válidos y definiciones de estado](#valid-states).

## Estados válidos y definiciones de estado
<a name="valid-states"></a>

En esta sección se describen las definiciones de estado de todos los estados válidos que se pueden usar en la máquina de estados de IDT. Algunos de los siguientes estados admiten configuraciones en el nivel de caso de prueba. Sin embargo, le recomendamos que configure las reglas de transición de estado en el nivel de grupo de pruebas en lugar de en el nivel del caso de prueba, a menos que sea absolutamente necesario.

**Topics**
+ [RunTask](#state-runtask)
+ [Choice](#state-choice)
+ [Parallel](#state-parallel)
+ [AddProductFeatures](#state-addproductfeatures)
+ [Informar](#state-report)
+ [LogMessage](#state-logmessage)
+ [SelectGroup](#state-selectgroup)
+ [Fail](#state-fail)
+ [Succeed](#state-succeed)

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

El estado `RunTask` ejecuta casos de prueba a partir de un grupo de pruebas definido en el conjunto de pruebas.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Next`  
El nombre del estado al que se realizará la transición después de ejecutar las acciones en el estado actual.

`TestGroup`  
Opcional. El ID del grupo de pruebas que se va a ejecutar. Si no se especifica este valor, IDT ejecuta el grupo de pruebas que seleccione el ejecutor de la prueba.

`TestCases`  
Opcional. Una matriz de casos de prueba IDs del grupo especificado en`TestGroup`. En función de los valores de `TestGroup` y `TestCases`, IDT determina el comportamiento de la ejecución de la prueba de la siguiente manera:   
+ Cuando se especifica `TestGroup` y `TestCases`, IDT ejecuta los casos de prueba especificados del grupo de pruebas. 
+ Cuando se especifica `TestCases`, pero no se especifica `TestGroup`, IDT ejecuta los casos de prueba especificados.
+ Cuando se especifica `TestGroup`, pero no se especifica `TestCases`, IDT ejecuta todos los casos de prueba del grupo de pruebas especificado.
+ Si no se especifica `TestGroup` ni `TestCases`, IDT ejecuta todos los casos de prueba del grupo de pruebas que el ejecutor de la prueba selecciona en la CLI de IDT. Para habilitar la selección de grupos para los ejecutores de las pruebas, debe incluir los estados `RunTask` y `Choice` en el archivo `state_machine.json`. Para ver un ejemplo de cómo funciona, consulte [Ejemplo de máquina de estados: ejecutar grupos de prueba seleccionados por el usuario](#allow-specific-groups).

  Para obtener más información sobre cómo habilitar los comandos CLI de IDT para los ejecutores de pruebas, consulte [Habilitación de comandos de CLI de IDT](create-test-executables.md#idt-cli-coop).

`ResultVar`  
El nombre de la variable de contexto que se va a configurar con los resultados de la prueba. No especifique este valor si no especificó ningún valor para `TestGroup`. IDT establece el valor de la variable que defina en `ResultVar` como `true` o `false` en función de lo siguiente:   
+ Si el nombre de la variable tiene el formato `text_text_passed`, el valor se establece en función de si todas las pruebas del primer grupo de pruebas se aprobaron o se omitieron.
+ En todos los demás casos, el valor se establece en función de si todas las pruebas de todos los grupos de pruebas se aprobaron o se omitieron.

Normalmente, se utiliza el `RunTask` estado para especificar un ID de grupo de pruebas sin especificar un caso de prueba individual IDs, de modo que IDT ejecutará todos los casos de prueba del grupo de pruebas especificado. Todos los casos de prueba ejecutados por este estado se ejecutan en paralelo, en orden aleatorio. Sin embargo, si todos los casos de prueba requieren la ejecución de un dispositivo y solo hay un dispositivo disponible, los casos de prueba se ejecutarán secuencialmente. 

**Error handling (Control de errores)**

Si alguno de los grupos de pruebas o casos IDs de prueba especificados no es válido, este estado genera el error de `RunTaskError` ejecución. Si el estado encuentra un error de ejecución, también establece la variable `hasExecutionError` en el contexto de la máquina de estados en `true`.

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

El estado `Choice` le permite configurar dinámicamente el siguiente estado al que realizar la transición en función de las condiciones definidas por el usuario.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Default`  
El estado predeterminado al que se realizará la transición si no se puede evaluar ninguna de las expresiones definidas en `Choices` como `true`.

`FallthroughOnError`  
Opcional. Especifica el comportamiento cuando el estado encuentra un error al evaluar las expresiones. Establézcalo en `true` si desea omitir una expresión si la evaluación genera un error. Si ninguna expresión coincide, la máquina de estados pasa al estado `Default`. Si no se especifica el valor `FallthroughOnError`, se establece de forma predeterminada en `false`. 

`Choices`  
Una matriz de expresiones y estados para determinar a qué estado hacer la transición después de ejecutar las acciones en el estado actual.    
`Choices.Expression`  
Una cadena de expresión que se evalúa como un valor booleano. Si la expresión se evalúa como `true`, la máquina de estados pasa al estado definido en `Choices.Next`. Las cadenas de expresión recuperan los valores del contexto de la máquina de estados y, a continuación, realizan operaciones en ellos para obtener un valor booleano. Para obtener información sobre cómo acceder al contexto de la máquina de estados, consulte [Contexto de la máquina de estados](#state-machine-context).   
`Choices.Next`  
El nombre del estado al que se realizará la transición si la expresión definida en `Choices.Expression` se evalúa como `true`.

**Error handling (Control de errores)**

El estado `Choice` puede requerir la gestión de errores en los siguientes casos: 
+ Algunas variables de las expresiones de elección no existen en el contexto de la máquina de estados.
+ El resultado de una expresión no es un valor booleano.
+ El resultado de una búsqueda en JSON no es una cadena, un número ni un booleano.

No puede usar un bloque `Catch` para gestionar los errores en este estado. Si quiere detener la ejecución de la máquina de estados cuando encuentre un error, debe establecer `FallthroughOnError` en `false`. Sin embargo, le recomendamos que establezca `FallthroughOnError` en `true` y, en función de su caso de uso, haga una de las siguientes opciones:
+ Si se espera que una variable a la que está accediendo no exista en algunos casos, utilice el valor `Default` y los bloques `Choices` adicionales para especificar el siguiente estado.
+ Si una variable a la que está accediendo debe existir siempre, defina el estado `Default` en `Fail`.

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

El estado `Parallel` le permite definir y ejecutar nuevas máquinas de estados en paralelo entre sí.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Next`  
El nombre del estado al que se realizará la transición después de ejecutar las acciones en el estado actual.

`Branches`  
Una matriz de definiciones de máquinas de estados para ejecutar. Cada definición de máquina de estados debe contener sus propios estados `StartAt`, `Succeed` y `Fail`. Las definiciones de máquinas de estados de esta matriz no pueden hacer referencia a estados ajenos a su propia definición.   
Como cada máquina de estados de la rama comparte el mismo contexto de máquina de estados, establecer variables en una rama y, a continuación, leer esas variables desde otra rama podría provocar un comportamiento inesperado.

El estado `Parallel` pasa al siguiente estado solo después de ejecutar todas las máquinas de estados de rama. Cada estado que requiera un dispositivo esperará para ejecutarse hasta que el dispositivo esté disponible. Si hay varios dispositivos disponibles, este estado ejecuta casos de prueba de varios grupos en paralelo. Si no hay suficientes dispositivos disponibles, los casos de prueba se ejecutarán secuencialmente. Como los casos de prueba se ejecutan en orden aleatorio cuando se ejecutan en paralelo, se podrían usar diferentes dispositivos para ejecutar pruebas del mismo grupo de pruebas. 

**Error handling (Control de errores)**

Asegúrese de que tanto la máquina de estados de la rama como la máquina de estados principal pasen al estado `Fail` para gestionar los errores de ejecución. 

Como las máquinas de estados de la rama no transmiten los errores de ejecución a la máquina de estados principal, no puede usar un bloque `Catch` para gestionar los errores de ejecución en las máquinas de estados de la rama. En su lugar, utilice el valor `hasExecutionErrors` en el contexto de la máquina de estados compartida. Para ver un ejemplo de cómo funciona, consulte [Ejemplo de máquina de estados: ejecutar dos grupos de prueba en paralelo](#run-in-parallel).

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

El estado `AddProductFeatures` le permite añadir características del producto al archivo `awsiotdevicetester_report.xml` generado por IDT. 

Una característica del producto es información definida por el usuario sobre los criterios específicos que puede cumplir un dispositivo. Por ejemplo, la característica del producto `MQTT` puede indicar que el dispositivo publica los mensajes MQTT correctamente. En el informe, las características del producto se establecen como `supported`, `not-supported` o como un valor personalizado, en función de si se han superado las pruebas especificadas.



**nota**  
El estado `AddProductFeatures` no genera informes por sí mismo. Este estado debe realizar la transición al [estado `Report`](#state-report) para generar informes.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Next`  
El nombre del estado al que se realizará la transición después de ejecutar las acciones en el estado actual.

`Features`  
Una matriz de características del producto para mostrar en el archivo `awsiotdevicetester_report.xml`.    
`Feature`  
El nombre de la característica  
`FeatureValue`  
Opcional. El valor personalizado que se utilizará en el informe en lugar de `supported`. Si no se especifica este valor, según los resultados de las pruebas, el valor de la característica se establece en `supported` o `not-supported`.   
Si utiliza un valor personalizado para `FeatureValue`, puede probar la misma característica con diferentes condiciones e IDT concatena los valores de la característica para las condiciones admitidas. Por ejemplo, en el siguiente fragmento se muestra la característica `MyFeature` con dos valores de característica distintos:  

```
...
{
    "Feature": "MyFeature",
    "FeatureValue": "first-feature-supported",
    "Groups": ["first-feature-group"]
},
{
    "Feature": "MyFeature",
    "FeatureValue": "second-feature-supported",
    "Groups": ["second-feature-group"]
},
...
```
Si ambos grupos de pruebas aprueban, el valor de la característica se establece en `first-feature-supported, second-feature-supported`.   
`Groups`  
Opcional. Matriz de grupos de prueba IDs. Para que la característica sea compatible, deben superan la prueba todas las pruebas de cada grupo de pruebas especificado.  
`OneOfGroups`  
Opcional. Una matriz de grupos de prueba IDs. Para que la característica sea compatible, deben aprobarse todas las pruebas de al menos uno de los grupos de pruebas especificados.   
`TestCases`  
Opcional. Una serie de casos de prueba IDs. Si especifica este valor, se aplicará lo siguiente:  
+ Para que la característica sea compatible, deben superan la prueba todos los casos de prueba especificados.
+ `Groups` debe contener solo un ID de grupo de pruebas.
+ `OneOfGroups` no debe especificarse.  
`IsRequired`  
Opcional. Establézcalo en `false` para marcar esta característica como una característica opcional en el informe. El valor predeterminado es `true`.  
`ExecutionMethods`  
Opcional. Una matriz de métodos de ejecución que coinciden con el valor `protocol` especificado en el archivo `device.json`. Si se especifica este valor, los ejecutores de pruebas deben especificar un valor `protocol` que coincida con uno de los valores de esta matriz para incluir la característica en el informe. Si no se especifica este valor, la característica siempre se incluirá en el informe.

Para usar el estado `AddProductFeatures`, debe establecer el valor de `ResultVar` con estado `RunTask` en uno de los siguientes valores:
+ Si especificó un caso de prueba individual IDs, `ResultVar` configúrelo en`group-id_test-id_passed`.
+ Si no especificó un caso de prueba individual IDs, `ResultVar` configúrelo en`group-id_passed`.

El estado `AddProductFeatures` comprueba los resultados de las pruebas de la siguiente manera: 
+ Si no especificó ningún caso de prueba IDs, el resultado de cada grupo de prueba se determina a partir del valor de la `group-id_passed` variable en el contexto de la máquina de estados.
+ Si especificó un caso de prueba IDs, el resultado de cada una de las pruebas se determina a partir del valor de la `group-id_test-id_passed` variable en el contexto de la máquina de estados.

**Error handling (Control de errores)**

Si un identificador de grupo proporcionado en este estado no es un identificador de grupo válido, este estado provoca un error de ejecución de `AddProductFeaturesError`. Si el estado encuentra un error de ejecución, también establece la variable `hasExecutionErrors` en el contexto de la máquina de estados en `true`.

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

El estado `Report` genera los archivos `suite-name_Report.xml` y `awsiotdevicetester_report.xml`. Este estado también transmite el informe a la consola.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Next`  
El nombre del estado al que se realizará la transición después de ejecutar las acciones en el estado actual.

Siempre debe pasar al estado `Report` que se encuentra al final del flujo de ejecución de la prueba para que los ejecutores de la prueba puedan ver los resultados de la prueba. Normalmente, el siguiente estado después de este estado es `Succeed`. 

**Error handling (Control de errores)**

Si este estado tiene problemas con la generación de los informes, se produce el error de ejecución `ReportError`. 

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

El estado `LogMessage` genera el archivo `test_manager.log` y transmite el mensaje de registro a la consola.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Next`  
El nombre del estado al que se realizará la transición después de ejecutar las acciones en el estado actual.

`Level`  
El nivel de error en el que se va a crear el mensaje de registro. Si especifica un nivel que no es válido, este estado genera un mensaje de error y lo descarta. 

`Message`  
El mensaje para registrar.

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

El estado `SelectGroup` actualiza el contexto de la máquina de estados para indicar qué grupos están seleccionados. Los valores establecidos por este estado se utilizan en cualquier estado `Choice` posterior.

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Next`  
El nombre del estado al que se realizará la transición después de ejecutar las acciones en el estado actual.

`TestGroups`  
Una matriz de grupos de pruebas que se marcarán como seleccionados. Para cada ID de grupo de pruebas de esta matriz, la variable `group-id_selected` se establece `true` en el contexto. Asegúrese de proporcionar un grupo de prueba válido, IDs ya que IDT no valida la existencia de los grupos especificados.

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

El estado `Fail` indica que la máquina de estados no se ejecutó correctamente. Este es el estado final de la máquina de estados y cada definición de la máquina de estados debe incluir este estado.

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

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

El estado `Succeed` indica que la máquina de estados se ejecutó correctamente. Este es el estado final de la máquina de estados y cada definición de la máquina de estados debe incluir este estado.

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

## Contexto de la máquina de estados
<a name="state-machine-context"></a>

El contexto de la máquina de estados es un documento JSON de solo lectura que contiene datos que están disponibles para la máquina de estados durante la ejecución. Solo se puede acceder al contexto de la máquina de estados desde la máquina de estados y contiene información que determina el flujo de prueba. Por ejemplo, puede usar la información configurada por los ejecutores de la prueba en el archivo `userdata.json` para determinar si es necesario ejecutar una prueba específica.

El contexto de la máquina de estados usa el siguiente formato:

```
{
    "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`  
Información sobre el grupo de dispositivos seleccionado para la ejecución de la prueba. Para un grupo de dispositivos seleccionados, esta información se recupera del elemento correspondiente de la matriz del grupo de dispositivos de alto nivel definido en el archivo `device.json`.

`userData`  
Información en el archivo `userdata.json`.

`config`  
Información del archivo `config.json`.

`suiteFailed`  
El valor se establece en `false` cuando se inicia la máquina de estados. Si un grupo de pruebas falla en un estado `RunTask`, este valor se establece en `true` durante el resto de la ejecución de la máquina de estados.

`specificTestGroups`  
Si el responsable de la prueba selecciona grupos de pruebas específicos para ejecutarlos en lugar de todo el conjunto de pruebas, se crea esta clave y contiene la lista de grupos IDs de pruebas específicos.

`specificTestCases`  
Si el ejecutor de la prueba selecciona casos de prueba específicos para ejecutarlos en lugar de todo el conjunto de pruebas, se crea esta clave y contiene la lista de casos de prueba específicos IDs.

`hasExecutionErrors`  
No se cierra cuando se inicia la máquina de estados. Si algún estado detecta errores de ejecución, se crea esta variable y se establece en `true` durante el resto de la ejecución de la máquina de estados.

Puede consultar el contexto mediante la JSONPath notación. La sintaxis de las JSONPath consultas en las definiciones de estado es`{{$.query}}`. Puede utilizar JSONPath las consultas como cadenas de marcadores de posición en algunos estados. IDT reemplaza las cadenas de marcadores de posición por el valor de la JSONPath consulta evaluada en el contexto. Puede utilizar los siguientes marcadores de posición para los siguientes valores:
+ El valor `TestCases` en estados `RunTask`. 
+ El valor `Expression` en estado `Choice`.

Cuando accede a los datos del contexto de la máquina de estados, asegúrese de que se cumplan las siguientes condiciones: 
+ Sus rutas de JSON deben comenzar por `$.`
+ Cada valor debe evaluarse como una cadena, un número o un booleano.

Para obtener más información sobre el uso de la JSONPath notación para acceder a los datos del contexto, consulte. [Uso del contexto de IDT](idt-context.md)

## Errores de ejecución
<a name="execution-errors"></a>

Los errores de ejecución son errores en la definición de la máquina de estados que esta encuentra al ejecutar un estado. IDT registra la información sobre cada error en el archivo `test_manager.log` y transmite el mensaje de registro a la consola.

Puede utilizar los siguientes métodos para gestionar los errores de ejecución:
+ Añada un [bloque `Catch`](#catch) a la definición de estado.
+ Compruebe el valor del [valor `hasExecutionErrors`](#context) en el contexto de la máquina de estados.

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

Para usar `Catch`, añada lo siguiente a su definición de estado:

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

Todos los campos que contienen valores son obligatorios tal y como se describe aquí:

`Catch.ErrorEquals`  
Una matriz de los tipos de error que se deben capturar. Si un error de ejecución coincide con uno de los valores especificados, la máquina de estados pasa al estado especificado en `Catch.Next`. Consulte la definición de cada estado para obtener información sobre el tipo de error que genera.

`Catch.Next`  
El siguiente estado al que se realizará la transición si el estado actual encuentra un error de ejecución que coincide con uno de los valores especificados en `Catch.ErrorEquals`.

Los bloques Catch se gestionan secuencialmente hasta que uno coincide. Si los errores no coinciden con los enumerados en los bloques Catch, las máquinas de estado seguirán ejecutándose. Como los errores de ejecución son el resultado de definiciones de estado incorrectas, se recomienda que pase al estado de Error cuando un estado detecte un error de ejecución.

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

Cuando algunos estados encuentran errores de ejecución, además de emitir el error, también establecen el valor `hasExecutionError` en `true` en el contexto de la máquina de estados. Puede usar este valor para detectar cuándo se produce un error y, a continuación, usar un estado `Choice` para hacer la transición de la máquina de estados al estado `Fail`.

Este método incluye las siguientes características:
+ La máquina de estados no comienza con ningún valor asignado a `hasExecutionError` y este valor no está disponible hasta que se establezca en un estado concreto. Esto significa que debe establecer explícitamente `FallthroughOnError` en `false` para los estados `Choice` que acceden a este valor para evitar que la máquina de estados se detenga si no se produce ningún error de ejecución. 
+ Una vez establecido en `true`, `hasExecutionError` nunca se establece en falso ni se elimina del contexto. Esto significa que este valor solo es útil la primera vez que se establece en `true` y, para todos los estados posteriores, no proporciona un valor significativo.
+ El valor `hasExecutionError` se comparte con todas las máquinas de estados de la rama con el estado `Parallel`, lo que puede provocar resultados inesperados en función del orden en que se acceda a él.

Debido a estas características, no recomendamos utilizar este método si se puede utilizar un bloque Catch en su lugar. 

## Máquinas de estados de ejemplo
<a name="state-machine-examples"></a>

En esta sección se proporcionan algunos ejemplos de configuraciones de máquinas de estados.

**Topics**
+ [Ejemplo de máquina de estados: ejecutar un solo grupo de pruebas](#single-test-group)
+ [Ejemplo de máquina de estados: ejecutar grupos de pruebas seleccionados por el usuario](#allow-specific-groups)
+ [Ejemplo de máquina de estados: ejecutar un solo grupo de pruebas con características de productos](#run-with-product-features)
+ [Ejemplo de máquina de estados: ejecutar dos grupos de prueba en paralelo](#run-in-parallel)

### Ejemplo de máquina de estados: ejecutar un solo grupo de pruebas
<a name="single-test-group"></a>

Esta máquina de estados:
+ Ejecuta el grupo de pruebas con ID `GroupA`, que debe estar presente en el conjunto de un archivo `group.json`.
+ Comprueba si hay errores de ejecución y pasa a `Fail` si se encuentra alguno.
+ Genera un informe y pasa a `Succeed` si no hay errores y a `Fail` en caso contrario.

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

### Ejemplo de máquina de estados: ejecutar grupos de pruebas seleccionados por el usuario
<a name="allow-specific-groups"></a>

Esta máquina de estados:
+ Comprueba si el ejecutor de pruebas seleccionó grupos de pruebas específicos. La máquina de estados no comprueba si hay casos de prueba específicos porque los ejecutores de pruebas no pueden seleccionar casos de prueba sin seleccionar también un grupo de pruebas.
+ Si se seleccionan grupos de pruebas: 
  + Ejecuta los casos de prueba dentro de los grupos de pruebas seleccionados. Para ello, la máquina de estados no especifica explícitamente ningún grupo de pruebas o casos de prueba en el estado `RunTask`.
  + Genera un informe después de ejecutar todas las pruebas y sale.
+ Si no se seleccionan grupos de pruebas:
  + Ejecuta las pruebas del grupo de pruebas `GroupA`.
  + Genera informes y sale.

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

### Ejemplo de máquina de estados: ejecutar un solo grupo de pruebas con características de productos
<a name="run-with-product-features"></a>

Esta máquina de estados:
+ Ejecuta el grupo de pruebas `GroupA`.
+ Comprueba si hay errores de ejecución y pasa a `Fail` si se encuentra alguno.
+ Añade la característica `FeatureThatDependsOnGroupA` al archivo `awsiotdevicetester_report.xml`:
  + Si `GroupA` supera la prueba, la característica se establece en `supported`.
  + La característica no se marca como opcional en el informe.
+ Genera un informe y pasa a `Succeed` si no hay errores y a `Fail` en caso contrario.

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

### Ejemplo de máquina de estados: ejecutar dos grupos de prueba en paralelo
<a name="run-in-parallel"></a>

Esta máquina de estados:
+ Ejecuta los grupos de pruebas `GroupA` y `GroupB` en paralelo. Las variables `ResultVar` almacenadas en el contexto por los estados `RunTask` de las máquinas de estados de la rama están disponibles para el estado `AddProductFeatures`.
+ Comprueba si hay errores de ejecución y pasa a `Fail` si se encuentra alguno. Esta máquina de estados no utiliza un bloque `Catch` porque ese método no detecta errores de ejecución en las máquinas de estados de la rama.
+ Agrega características al archivo `awsiotdevicetester_report.xml` en función de los grupos que aprueban
  + Si `GroupA` supera la prueba, la característica se establece en `supported`.
  + La característica no se marca como opcional en el informe.
+ Genera un informe y pasa a `Succeed` si no hay errores y a `Fail` en caso contrario.

Si hay dos dispositivos configurados en el grupo de dispositivos, ambos `GroupA` y `GroupB` pueden ejecutarse al mismo tiempo. Sin embargo, si `GroupA` o `GroupB` incluyen varias pruebas, es posible que ambos dispositivos se asignen a esas pruebas. Si solo se configura un dispositivo, los grupos de prueba se ejecutarán secuencialmente.

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