# Tests inestables de Bazel {#bazel-flaky-tests}

> [!IMPORTANT]
> **Requisitos**
>
> - <.localized_link href="/guides/features/test-insights/bazel">Análisis de tests de Bazel</.localized_link> configurado mediante `tuist bazel setup`.

Los tests inestables son tests que producen resultados diferentes (aprobado o fallido) cuando se ejecutan varias veces con el mismo código. Minan la confianza en tu suite de tests y hacen perder tiempo a los desarrolladores al investigar fallos falsos. Tuist detecta automáticamente los tests inestables y te ayuda a hacerles seguimiento a lo largo del tiempo.


## Cómo funciona la detección de inestabilidad {#how-it-works}

Tuist utiliza los casos individuales de los informes `test.xml` de Bazel para detectar resultados inconsistentes entre reintentos y entre ejecuciones de la misma confirmación y selección de objetivos en integración continua. Las ejecuciones locales siguen siendo visibles, pero no marcan automáticamente los casos de test como inestables.

### Reintentos de tests {#test-retries}

Los reintentos son opcionales e independientes de la cuarentena. `--flaky_test_attempts=3` habilita hasta **tres intentos totales de Bazel** por test, no tres reintentos adicionales. Mantén tu configuración de reintentos existente en `.bazelrc` o pásala explícitamente:

```sh
tuist bazel test -- --flaky_test_attempts=3 //app:tests
```

Los reintentos deben ejecutarse realmente para que Tuist observe sus resultados. El resumen de inestabilidad de un objetivo de Bazel por sí solo no identifica qué caso individual fue inestable.

### Detección entre ejecuciones {#cross-run-detection}

Comparar ejecuciones requiere metadatos de confirmación y rama. Proporciónalos cuando tu entorno de compilación no los publique ya:

```sh
tuist bazel test -- \
  --build_metadata=CI=true \
  --build_metadata=GIT_COMMIT="$GIT_COMMIT" \
  --build_metadata=GIT_BRANCH="$GIT_BRANCH" //app:tests
```

Los casos se identifican por la etiqueta del objetivo, el nombre de la clase (con fallback al nombre de la suite) y el nombre del test, como se describe en <.localized_link href="/guides/features/test-insights/bazel">Análisis de tests de Bazel</.localized_link>.

## Gestión de tests inestables {#managing-flaky-tests}

### Limpieza automática {#automatic-clearing}

La detección y la limpieza se gestionan mediante una **alerta de automatización** en el proyecto. Cada proyecto incluye una automatización predeterminada llamada "Detección de tests inestables" cuyo *disparador* marca un test como inestable y cuya *recuperación* elimina la marca cuando el test ha superado el periodo de recuperación configurado (por defecto, **14 días**) sin volver a activarse. Edítala en **Configuración → Automatizaciones** para cambiar el periodo de recuperación, modificar las acciones de recuperación (por ejemplo, liberar también el test de la cuarentena) o desactivar por completo la recuperación para que los tests permanezcan marcados como inestables hasta que los limpies manualmente.

### Gestión manual {#manual-management}

También puedes marcar o desmarcar manualmente los tests como inestables desde la página de detalles del caso de test. Esto resulta útil cuando:
- Quieres reconocer un test inestable conocido mientras trabajas en su corrección
- Un test se marcó incorrectamente debido a problemas de infraestructura


## Poner en cuarentena tests inestables {#quarantining}

La cuarentena aísla un test inestable para que no bloquee la CI mientras lo corriges. Por defecto es una **acción manual**: pones un test en cuarentena, lo liberas y cambias de modo desde la página de detalles del caso de test en el dashboard. También puedes vincularlo a una **alerta de automatización** en **Settings → Automations** para que el test se silencie automáticamente (o se omita) cuando supere un umbral de inestabilidad, y se libere cuando se recupere. Cada transición, manual o automática, queda registrada en el registro de auditoría del caso de test.

Por defecto, la recuperación espera hasta que la condición de activación deja de cumplirse, por lo que un test permanece en cuarentena hasta que sus ejecuciones inestables anteriores salen de la ventana de activación. Para recuperarlo antes, configura **Recover when** como **No new flaky runs**: el test se recupera una vez que transcurre la ventana de recuperación (días o ejecuciones) sin ninguna nueva ejecución inestable, cada nueva ejecución inestable reinicia esa espera y, tras la recuperación, solo una nueva ejecución inestable lo vuelve a poner en cuarentena.


`tuist bazel test` obtiene la política de cuarentena antes de cada invocación y la aplica a la ejecución subyacente de `bazel test`. Un `bazel test` normal sigue informando de los resultados de los tests, pero no aplica la cuarentena:

```sh
tuist bazel test -- //app:tests
```

Los argumentos después de `--` se reenvían a `bazel test`. Usa `--path` para seleccionar el proyecto y el directorio de trabajo, y `--bazel` para seleccionar un ejecutable diferente, como `bazelisk`. Una configuración de Bazel con nombre, como `--config=ci`, es opcional y funciona de la misma manera.

### Silenciar {#mute}

Usa **Silenciar** como flujo de trabajo principal de cuarentena. Los casos silenciados siguen ejecutándose, sus fallos permanecen visibles y los casos hermanos sanos siguen afectando al resultado. Tuist convierte la salida de fallo de test de Bazel en éxito solo cuando los informes atribuyen cada fallo en cada objetivo fallido a un caso silenciado. Los errores de compilación, los tiempos de espera agotados, las ejecuciones interrumpidas, los informes faltantes o incompletos y los fallos fuera del conjunto silenciado mantienen el estado de fallo de Bazel.

### Omitir {#skip}

La omisión funciona por objetivo de Bazel: omitir un caso excluye todo su objetivo, incluidos los casos sanos, porque Bazel no puede filtrar casos individuales para cada framework de tests. Prefiere **Silenciar** a menos que pretendas excluir el objetivo completo. El comando imprime todas las etiquetas de objetivo excluidas para que los registros de compilación muestren qué dejó fuera la política de cuarentena.

Si un objetivo omitido ya no existe, Tuist lo nombra en una advertencia y se ejecuta sin esa exclusión. Devuelve los casos obsoletos a **Habilitado** para eliminar sus políticas permanentemente. Si no queda ningún objetivo de test, Bazel mantiene su estado de salida normal de "no se encontraron tests".

### Por qué los tests en cuarentena pueden aparecer como aprobados {#quarantined-passing}

- Los **tests silenciados** siguen ejecutándose. Un test silenciado que falla se registra como **fallido** en la ejecución del caso de test y se marca como inestable; el estado por test no se sobrescribe. Lo que se sobrescribe es la **ejecución de tests completa**: si todos los casos de test que fallan en la ejecución están silenciados, la ejecución en su conjunto se informa como aprobada, de modo que los fallos silenciados no rompen la CI.
- Los **tests omitidos** no se ejecutan en absoluto, por lo que el panel sigue mostrando el estado de la última ejecución real del test. Esa instantánea puede tener semanas de antigüedad.


### Volver a ejecutar tests en cuarentena {#running-quarantined-tests-again}

Para investigar o validar una corrección, omite la política de cuarentena:

```sh
tuist bazel test --no-quarantine -- --nocache_test_results //app:tests
```

Devuelve el caso a **Habilitado** para incluir su objetivo en ejecuciones normales posteriores. Los casos omitidos no generan nuevas ejecuciones hasta que se incluyan explícitamente, por lo que una automatización basada en nuevas ejecuciones exitosas necesita una ejecución de validación antes de poder recuperarlos.

### Limitaciones {#limitations}

- Un `--build_event_json_file` o `--target_pattern_file` explícito no se puede combinar con una cuarentena activa. Pasa los patrones de objetivo directamente.
- Si Tuist no puede obtener la política de cuarentena, el comando se detiene antes de ejecutar los tests. Nunca aplica una política parcial. Usa `--no-quarantine` cuando quieras ejecutar intencionadamente sin ella.
- Un fallo que coincide con un silenciamiento registrado bajo una identidad anterior basada en la suite sigue siendo bloqueante, y el comando nombra la política que debe volver a aplicarse.

Consulta los [filtros de tests](https://bazel.build/docs/user-manual#test-filter), las [opciones de comando](https://bazel.build/reference/command-line-reference) y las [descripciones de eventos de compilación](https://bazel.build/remote/bep-glossary) de Bazel para conocer el comportamiento subyacente.

## Notificaciones de Slack {#slack-notifications}

Recibe notificaciones cuando un test se vuelva inestable configurando <.localized_link href="/guides/integrations/slack#flaky-test-alerts">alertas de tests inestables</.localized_link> en tu integración con Slack.


## Consulta del estado de tests inestables y en cuarentena {#querying}

### CLI {#querying-cli}

El árbol de comandos `tuist test case` expone toda la información que Tuist rastrea sobre un caso de test:

```sh
tuist test case list --flaky                       # only flaky test cases
tuist test case list --quarantined                 # only muted or skipped test cases
tuist test case show <test_case_id>                # detail: flakiness rate, last status, run counts
tuist test case events <test_case_id>              # audit log: marked_flaky, muted, skipped, ...
tuist test case run list <test_case_id>            # run history with status and duration
tuist test case run show <test_case_run_id>        # single run, including failure breakdown
```

Todos ellos aceptan `--json` para su uso en scripts.

### API REST {#querying-rest-api}

Los mismos datos están disponibles a través de HTTP. Consulta los [endpoints de casos de test](https://tuist.dev/api/docs#tag/test-cases) en la referencia de la API para obtener la lista completa de rutas, filtros y campos de respuesta. Para cambiar el estado de un caso de test (marcar o desmarcar como inestable, silenciar, omitir), envía `PATCH /api/projects/{account_handle}/{project_handle}/tests/test-cases/{test_case_id}` con `is_flaky` o `state`. El mismo cambio está disponible como `tuist test case update` y como la herramienta MCP `update_test_case`.

