Un cambio en un servicio de pagos puede pasar miles de unit tests y aun así romper producción porque el API de facturación interpreta una clave de idempotencia de forma distinta a lo que el servicio espera. El fallo puede pasar desapercibido hasta que un job de integración nocturno llegue a la interfaz, mucho después de que el commit haya avanzado por la parte rápida del pipeline.
Ese es el problema operativo de las pruebas de integración CI/CD. Los unit tests demuestran que la lógica aislada funciona correctamente. Los integration tests aportan evidencia de que los componentes, servicios, schemas, queues y dependencias externas siguen sincronizados. En un pipeline de entrega moderno, esa evidencia debería guiar las decisiones de triage, no convertirse en un muro de checks lentos que los desarrolladores aprendan a ignorar.
CI/CD se ha convertido en un modelo estándar de entrega de software. Un informe de pruebas DevOps 2024 de mabl dice que casi el 90% de las organizaciones globales están priorizando transformaciones DevOps, mientras que menos del 50% de los testers participan en la definición y mantenimiento de procesos CI/CD y solo el 10% de las organizaciones reporta que no implementa CI/CD en absoluto. La consecuencia práctica es clara: la verificación de integración ahora debe operar a escala de entrega.
Table of Contents
- Por qué el Integration Testing es el punto de control de CI/CD
- Dónde se ubican los Integration Tests entre Unit y End to End
- Gestión de entornos y datos para tests fieles
- Ejemplos de pipeline para GitHub Actions, GitLab CI y Jenkins
- Tácticas de fiabilidad para tests de integración inestables
- Políticas de gating y reglas de promoción de despliegue
- Checklist de adopción y observabilidad para confianza a largo plazo
Por qué las pruebas de integración son el punto de control de CI/CD
En las pruebas de integración es donde el riesgo de release se vuelve concreto. Un unit test puede confirmar que un manejador de pagos formatea correctamente una clave de idempotencia, pero solo un integration test puede probar que el manejador, el cliente HTTP, el API de facturación, la capa de persistencia y el comportamiento de reintento funcionan en armonía.
Esto convierte a la etapa de integración en el punto de control natural entre la integración continua y la entrega continua. Un commit no debería considerarse deployable solo porque su suite de unit tests pase. Debe ganar su promoción generando evidencia confiable de que las interfaces que modifica siguen funcionando en un entorno similar a producción.

La distinción es clave porque una integración frecuente sin verificación automatizada solo acelera la propagación de defectos. Una revisión sistemática de enfoques para mejorar CI/CD identificó prioridades recurrentes como reducir el tiempo de build y test, mejorar la visibilidad de resultados, soportar continuous testing, detectar fallos y mejorar la fiabilidad del deployment. Otra revisión en la misma investigación define la integración continua en torno a la integración frecuente de code, verificada por un build automatizado que incluye tests para detectar defectos rápidamente.
Construye el punto de control con intención
Empieza clasificando los tests de integración según la decisión que respaldan:
- Tests bloqueantes protege contratos críticos y ejecútalos de forma síncrona antes de un merge o promoción.
- Tests en cuarentena siguen siendo visibles y generan evidencia, pero no bloquean el delivery mientras el equipo investiga su inestabilidad.
- Tests asíncronos ejecutan workflows más amplios, composiciones completas en staging o infraestructura costosa tras pasar el gate rápido.
Esto es más útil que debatir si cada test debe estar “en CI”. La pregunta clave es si un test es lo suficientemente fiable y valioso para influir en una decisión de promoción.
Regla práctica: Filtra según la evidencia de integración estable, no según la existencia de una suite de integración.
El resto de la implementación deriva de esa regla. Usa dependencias similares a producción donde una interfaz pueda fallar, paraleliza checks independientes, mide falsos fallos y define condiciones explícitas para cuarentena y promoción. Los equipos que quieran conectar esto con prácticas de delivery más amplias también pueden revisar los beneficios de la integración continua.
Dónde encajan los tests de integración entre Unit y End to End
La pirámide de testing es un modelo de costes, no una ley rígida. Los unit tests son rápidos porque aíslan una función, clase o módulo. Esa velocidad los hace ideales para obtener feedback inmediato, pero los mocks pueden ocultar precisamente los fallos que ocurren en las interfaces del sistema, como diferencias de serialización, restricciones de base de datos, configuración de autenticación o el comportamiento de las colas.
Los tests end-to-end ocupan la posición opuesta. Ejecutan el user journey a través de todo el stack, lo que los hace valiosos para workflows de alto riesgo. También cruzan límites de navegador, red, servicios e infraestructura, por lo que el diagnóstico y la estabilidad son más difíciles. Si cada merge debe esperar a toda la suite end-to-end, los devs reciben una señal lenta que a menudo aporta menos que un test de integración enfocado a nivel API.
Los tests de integración ocupan el punto medio. Utilizan dependencias reales o casi reales para verificar el comportamiento entre servicios sin requerir una orquestación completa de la UI. Esta capa puede cubrir llamadas HTTP y gRPC, publicación en colas, migraciones de base de datos, interacción con caché y compatibilidad de esquemas.
Tres patrones de integración útiles
Component tests in-process con Testcontainers inicia el componente de la aplicación junto con dependencias como PostgreSQL, Redis o Kafka. Este patrón justifica el coste de configuración cuando el riesgo de defectos afecta a la persistencia, serialización, transacciones o semántica de brokers. Proporciona una dependencia real al test manteniendo un límite de prueba estrecho.
Tests de contrato entre servicios con Pact o un schema registry se centran en el acuerdo entre consumidor y proveedor. Son una gran opción cuando los equipos lanzan servicios de forma independiente y necesitan feedback rápido sobre cambios en el contrato. Los contract tests no deben sustituir a los tests de integración de comportamiento, pero pueden evitar que una interfaz incompatible llegue a un entorno compartido.
Tests de nivel API contra un stack de staging compuesto llama a varios servicios desplegados a través de sus rutas de red reales. Usa este patrón para workflows donde el enrutamiento, la autenticación, el service discovery, la configuración de despliegue o las políticas de infraestructura sean críticos. Mantén el conjunto enfocado en rutas de negocio esenciales, ya que un stack de staging completo es más caro de aprovisionar y difícil de aislar si falla.
| Patrón | Runtime | Fidelidad del entorno | Ideal para |
|---|---|---|---|
| Component tests in-process con Testcontainers | Rápido a moderado | Dependencias reales seleccionadas | Comportamiento de base de datos, caché, broker y componentes |
| Tests de contrato consumidor-proveedor con Pact o registros de esquemas | Rápido | Alta fidelidad de interfaz | Compatibilidad de API y de eventos entre servicios publicados por separado |
| Tests de API contra un stack de staging compuesto | De moderado a lento | Alta fidelidad de sistema | Rutas de red, autenticación, routing y flujos críticos multi-servicio |
Mantén deliberadamente acotada la suite de merge síncrona. Un objetivo práctico es mantener el path de integración por debajo de 10 minutos por commit de merge, y luego pasa los escenarios amplios a ejecución asíncrona. Los equipos que quieran una base más amplia para esta división pueden consultar qué incluye el testing automatizado, pero el principio rector es simple: paga por realismo solo cuando cambie una decisión de release.
Gestión de entornos y datos para tests fieles
Un test en el entorno incorrecto puede dar una falsa sensación de seguridad. Un test en un entorno compartido inestable puede dar falsos errores. Un testing de Pruebas de integración en CI/CD necesita una estrategia de entornos que haga explícitos los límites de dependencia y el estado de los datos sea reproducible.

Empieza con dependencias que puedas ejecutar fielmente. Testcontainers puede aprovisionar instancias desechables de PostgreSQL, Redis y Kafka para cada job. La clave no es Docker en sí, sino el control sobre versiones, configuración, arranque y teardown.
Una secuencia de jobs reproducible
Usa una secuencia fija en lugar de dejar que el code improvise su setup:
- Arrancar dependencias. Levanta el contenedor de PostgreSQL y espera a un health check real en lugar de asumir que un proceso en ejecución está listo para recibir tráfico.
- Aplica las migraciones. Ejecuta la misma ruta de migración que usa la aplicación. No crees un esquema de pruebas manual que pueda desincronizarse de producción.
- Carga fixtures deterministas. Siembra solo los registros necesarios para el escenario y asigna datos aislados a cada job para que las ejecuciones en paralelo no muten su estado.
- Ejecuta aserciones de contrato. Verifica formatos de request, comportamiento de response, esquemas de eventos, transiciones de estado y resultados de persistencia.
- Limpia todo el entorno. Destruye contenedores y volúmenes temporales incluso si un test falla, para que los siguientes jobs no hereden un estado corrupto.
Un arranque de PostgreSQL de 90 segundos es un costo razonable si detecta defectos en migraciones y transacciones. Un cluster de staging completo es otra decisión: consume más infraestructura, introduce más drift de configuración y aumenta los puntos de fallo. Empieza con el entorno más estrecho y fiel posible, y amplíalo cuando la cobertura de contratos o incidentes en producción demuestren que falta un modo de fallo crítico.
Usa la virtualización con criterio
Algunos sistemas de terceros no pueden provisionarse de forma segura en cada pipeline. WireMock, Mountebank y Hoverfly pueden simular esas dependencias, pero la simulación debe tratarse como un contrato mantenido, no como una salida fácil. Un mock que solo devuelva respuestas ideales no revelará la expiración de autenticación, rate limiting, payloads malformados, manejo de timeouts o la evolución de esquemas.
Los entornos de preview efímeros son útiles cuando el riesgo depende de varios servicios desplegados trabajando en conjunto. Docker Compose puede ofrecer una composición local y de CI compacta, mientras que los namespaces de Kubernetes pueden aislar entornos de pull-request cuando el comportamiento del despliegue requiere pruebas. Sea cual sea el enfoque, fija las versiones de las dependencias y registra la configuración usada en cada ejecución.
Los secrets requieren la misma disciplina que los datos. Guarda las credenciales fuera de los test fixtures y rota el acceso mediante los mecanismos protegidos de la plataforma. El guía de Capgo para gestionar secrets en pipelines de CI/CD ofrece orientación relevante para mantener los valores sensibles fuera de la configuración del repositorio.
Un breve recorrido visual puede ayudar a los equipos a alinearse con el ciclo de vida del entorno:
Ejemplos de pipeline para GitHub Actions, GitLab CI y Jenkins
El runner importa menos que la estructura del workflow. Haz build una sola vez, provisiona dependencias de forma predecible, divide los grupos de tests independientes, publica resultados legibles por máquina y deja clara la barrera de bloqueo. La sintaxis cambia según la plataforma, pero esas reglas operativas se mantienen constantes.
Acciones de GitHub
Una matriz funciona bien cuando los tests de integración pueden dividirse por dominio o shard. Los service containers mantienen las dependencias cerca del runner, mientras que el output de JUnit ofrece un formato de resultado estable para los pull requests y sistemas downstream.
name: integration
on:
pull_request:
jobs:
integration:
strategy:
fail-fast: false
matrix:
suite: [billing, orders, notifications]
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: test
POSTGRES_DB: app_test
options: >-
--health-cmd "pg_isready -U postgres -d app_test"
--health-interval 5s
--health-timeout 5s
--health-retries 12
redis:
image: redis:7
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run test:integration, --suite=${{ matrix.suite }}
- if: always()
uses: actions/upload-artifact@v4
with:
name: junit-${{ matrix.suite }}
path: test-results/*.xml
Fijar las versiones de las actions y de las dependencias reduce el drift del entorno. GitHub Actions ofrece paralelismo principalmente mediante matrices y jobs separados; usa una matriz solo si cada shard tiene datos aislados y una duración predecible.
GitLab CI
GitLab CI permite separar la preparación, la ejecución de tests y el reporting. Los child pipelines son útiles cuando un repositorio grande gestiona múltiples servicios con distintos entornos de integración. Los artifacts preservan los resultados de JUnit incluso si el job de test falla.
stages:
- build
- integration
build-image:
stage: build
script:
- docker build --tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
integration:
stage: integration
parallel:
matrix:
- SUITE: [billing, orders, notifications]
image: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
services:
- name: postgres:16
alias: postgres
- name: redis:7
alias: redis
script:
- ./scripts/migrate-test-db.sh
- npm run test:integration, --suite="$SUITE" --reporter=junit
artifacts:
when: always
reports:
junit: test-results/*.xml
Usa child pipelines de GitLab cuando el ownership del servicio o la topología de despliegue dificulten mantener un único archivo monolítico. Deja que el parent pipeline se encargue de la decisión de promoción; de lo contrario, un child podría pasar mientras la señal de release general sigue siendo ambigua.
Jenkins
Jenkins es útil cuando los equipos necesitan agentes self-hosted o acceso a red poco habitual. Un Jenkinsfile declarativo puede asignar agentes basados en Docker y ejecutar suites en paralelo, pero el mantenimiento de plugins, controllers, agentes e imágenes corre por cuenta del equipo.
pipeline {
agent none
stages {
stage('Build') {
agent { docker 'node:22' }
steps {
sh 'npm ci'
sh 'npm run build'
stash name: 'build', includes: 'dist/**'
}
}
stage('Integration') {
parallel {
stage('Billing') {
agent { docker 'my-org/integration-runner:stable' }
steps {
unstash 'build'
sh './scripts/start-test-dependencies.sh'
sh 'npm run test:integration, --suite=billing'
}
}
stage('Orders') {
agent { docker 'my-org/integration-runner:stable' }
steps {
unstash 'build'
sh './scripts/start-test-dependencies.sh'
sh 'npm run test:integration, --suite=orders'
}
}
}
}
}
post {
always {
junit 'test-results/*.xml'
}
}
}
| Característica | Acciones de GitHub | GitLab CI | Jenkins |
|---|---|---|---|
| Ejecución en paralelo | Matrix jobs y jobs separados | parallel y jobs de matriz |
Declarativo parallel stages y agentes distribuidos |
| Control del entorno | Runners alojados o self-hosted | Runners alojados o self-hosted | Controlador y agentes autogestionados |
| Visibilidad de resultados | Artifacts y anotaciones de check | Reportes JUnit y artifacts | Publicador JUnit e historial de build |
| Reproducibilidad de versiones | Acciones, imágenes y versiones fijas | Imágenes fijas y configuración del runner | Imágenes de agentes y plugins controlados |
| Mejor ajuste operativo | Repositorios centrados en GitHub | Entrega centrada en GitLab | Equipos que requieren mucha personalización self-hosted |
Para equipos que ya usan GitHub, build y release automatizados con GitHub Actions puede ofrecer un patrón de despliegue útil. La decisión de diseño clave es la misma para los tres runners: no hagas que cada test costoso bloquee el merge de forma síncrona.
Tácticas de fiabilidad para tests de integración inestables
Los retries son útiles para el diagnóstico, pero los retries masivos son una mala estrategia de fiabilidad. Pueden convertir un defecto real en un build exitoso, ocultar inestabilidad ambiental y hacer que los dashboards de pass-rate parezcan mejores de lo que es el pipeline.
La magnitud del problema es evidente en los datos de ingeniería publicados. Google reportó que cerca de el 16% de las pruebas presentan flakiness y aproximadamente el 1.5% de todas las ejecuciones de pruebas devuelven un resultado flaky, mientras que otro estudio halló que el 4.56% de los fallos de pruebas en Google fueron causados por pruebas flaky, según se resume en la guía de AWS sobre pruebas de integración y entrega continua. Los datos de Google también mostraron sobre 84% de las transiciones de pass-to-fail en CI fueron flaky en lugar de bugs reales, y proyectos de Microsoft reportaron cerca del 4.6% de pruebas flaky en un estudio, según la revisión de estadísticas de tests flaky de Panto.

Mide antes de cambiar la política
Rastrea el flakiness como:
fallos flaky ÷ ejecuciones totales × 100
Usa una ventana de 7 a 30 días, y calcúlalo por suite, test, runner image, dependencia y entorno. Un test que falla solo en un runner requiere una solución distinta a uno que falla en todos los entornos.
Usa estas categorías de triaje:
- Fallo de producto: bloquea el gate correspondiente y arregla el code o el contrato.
- Fallo de entorno: reparar health checks, límites de recursos, redes o la configuración de dependencias.
- Fallo en el test: corregir el orden de las aserciones, el estado compartido, tiempos, limpieza o el diseño de fixtures.
- Inestabilidad no clasificada: pon en cuarentena temporalmente, pero asigna un propietario y una fecha de expiración.
Elimina las causas habituales
El estado mutable compartido crea dependencia del orden. Asigna a cada job esquemas aislados, identificadores únicos o un límite de rollback de transacciones. Los sistemas asíncronos requieren polling basado en condiciones con timeouts definidos, no sleeps arbitrarios. Inyecta relojes en la lógica de expiración y espera a que el contenedor esté sano en lugar de solo al inicio del proceso.
El sharding reduce el tiempo de ejecución, pero no arregla un test defectuoso. Ejecuta los shards de forma independiente, conserva los logs de cada uno y vuelve a ejecutar solo el test o shard fallido para el diagnóstico. No reinicies todo el pipeline solo porque un check de integración tuvo un fallo ambiental.
Un test solo puede salir de cuarentena tras cumplir una política de estabilidad definida, como ejecuciones exitosas consecutivas en los entornos donde se ejecutará. El equipo debe elegir el umbral exacto y registrarlo en la política. Lo importante es que la promoción se gana mediante estabilidad observada, no borrando la etiqueta de cuarentena.
Políticas de gating y reglas de promoción de despliegue
Un quality gate debe responder a una pregunta: ¿tiene este artefacto evidencia suficiente para pasar al siguiente entorno? No debe convertirse en un vertedero para todos los tests que la organización haya acumulado.
La brecha de cumplimiento es una advertencia. Una encuesta de 2025 citada por Análisis de pruebas de CI/CD de Testkube indica que el 72% de las organizaciones tienen QA automatizado en su CI/CD, mientras que solo un 26% impón quality gates que bloqueen el despliegue si los tests fallan. Adoptar esto sin aplicarlo deja la decisión de release a la memoria, la urgencia o una lista manual.
Usa gates específicos por etapa
Al hacer commit, bloquea con unit tests rápidos y un subconjunto de integración estable que proteja las interfaces críticas o modificadas. En staging, añade validaciones de configuración de despliegue y checks de entorno compuesto más amplios. Antes de producción, exige el artifact aprobado, la validación exitosa en entorno protegido y una aprobación explícita según tu modelo de riesgo.
| Etapa | Tasa de éxito requerida | Cuarentena permitida | Aprobación |
|---|---|---|---|
| Commit o pull request | Todos los checks bloqueantes pasan | Solo tests fuera del subset bloqueante | Protección de merge automatizada |
| Promoción a Staging | Todos los checks críticos pasan | Solo con owner y revisión de riesgo | Owner del equipo o servicio |
| Canary o rollout limitado | Checks de promoción y health signals pasan | Ningún test en quarantine cubre el path protegido | On-call o release owner |
| Promoción a producción | Todos los gates requeridos pasan con evidencia de auditoría | Sin cuarentena en rutas críticas | Aprobación explícita cuando la política lo requiera |
No confundas el "pass rate" con un objetivo de porcentaje bruto. Una suite puede mostrar un pass rate alto mientras falla repetidamente en la ruta exacta de pago o autenticación que importa. Define la cobertura de la ruta crítica por comportamiento y exige que esos checks pasen de forma determinista.
Haz visibles los bypasses
Configura la protección de ramas para que un check bloqueante impida el merge. Configura reglas de protección de entornos para que la promoción requiera las aprobaciones y los artifacts esperados. Un override manual puede ser necesario durante un incidente, pero debe requerir un motivo explícito, un aprobador asignado, un timestamp y un ticket de seguimiento.
La cuarentena no es un permiso para ignorar fallos. Es una forma controlada de mantener el delivery en marcha preservando la evidencia. Si un test en cuarentena cubre una ruta de release protegida, la política debe restaurar su estado de bloqueo o exigir una decisión de riesgo antes de la promoción.
Checklist de adopción y observabilidad para confianza a largo plazo
Los equipos suelen fallar en las integration testing de dos formas: o empiezan con una suite enorme que ralentiza cada merge, o crean una suite rápida con mocks tan amplios que nunca detectan los fallos que expone producción. Un plan de adopción por etapas evita ambas trampas.

Fase uno: haz que las señales actuales sean confiables
Empieza con el pipeline que ya tienes:
- Establece el primer gate: Identifica contratos de servicio críticos y haz que solo los checks estables sean bloqueantes.
- Define el comportamiento de reintentos: Permite reruns específicos para diagnóstico; evita reintentos silenciosos que conviertan un fallo en un éxito.
- Habilita la paralelización: Divide las suites por dominio, dependencia o shard, con datos aislados por job.
- Publica los resultados de los tests: Guarda reportes JUnit, logs, estado del contenedor y clasificación de fallos de cada ejecución.
En esta etapa, no busques la máxima cobertura. Elimina primero las fuentes de ruido más costosas y usa la confianza recuperada para ampliar la cobertura de dependencias reales.
Fase dos: aumenta la fidelidad del entorno
Añade Testcontainers para dependencias fáciles de reproducir. Introduce contract tests donde la propiedad de los servicios esté distribuida. Usa entornos efímeros cuando el enrutamiento, la configuración de despliegue o el comportamiento entre servicios no se puedan representar bien en un job compacto.
La decisión debe basarse en evidencias. Si un incidente en producción reveló un error de migración, añade una ruta de base de datos real. Si un API derivó entre servicios desplegados de forma independiente, añade un contrato consumer-provider. Si un fallo depende de la configuración de Kubernetes, ejecuta el check en un namespace efímero en lugar de fingir que un mock demuestra lo mismo.
Fase tres: conecta la observabilidad al triaje
Captura percentiles de duración de tests, diferencias de configuración de entorno, versiones de dependencias bloqueadas, ratios de reintentos y logs/traces de la app correlacionados mediante OpenTelemetry. Un dashboard útil debería mostrar:
- Tasa de flakiness: Qué suites y tests se están volviendo menos deterministas.
- Tiempo medio hasta el éxito: Cuánto tiempo pasa un pipeline fallido antes de recuperarse.
- Clusters de modos de fallo: Si los fallos se agrupan en torno a code, el entorno, dependencias o el diseño del test.
- Inventario de cuarentena: Qué tests están en cuarentena, quién es el responsable y cuándo deben revisarse.
- Evidencia de promoción: Qué gates se superaron antes de cada cambio de entorno.
Este es el significado operativo de la observabilidad de aplicacionesEl dashboard no es un archivo retrospectivo. Debe influir en la decisión de hoy sobre si un test bloquea, espera de forma asíncrona o vuelve a cuarentena.
Mantén una política de equipo de una sola página con el subset de bloqueo, reglas de cuarentena, dueños de entornos, límites de reintento, requisitos de artefactos y el proceso de override. Revísala cuando cambien los datos de fallos, no solo cuando un incidente mayor obligue a hablarlo.
Capgo ofrece integraciones de CI/CD para automatizar el upload de bundles de Live Update firmados tras un build web, con canales que soportan workflows de feature-branch, staging y producción. Si tu equipo de CapacitorJS o Electron necesita conectar la evidencia de integration-tests con la entrega controlada en móviles, visita Capgo para evaluar API y su workflow de rollout.