Por qué GitHub Actions para QA
GitHub Actions es la plataforma CI/CD integrada de GitHub. Si tu proyecto vive en GitHub, Actions elimina la necesidad de servicios CI/CD externos. Los workflows se ejecutan directamente dentro de GitHub, con integración estrecha con pull requests, issues y el ecosistema de GitHub.
Para ingenieros QA, esta integración estrecha es una gran ventaja. Los resultados de tests aparecen directamente en pull requests. Los checks fallidos bloquean merges. Los artefactos de tests son accesibles desde la misma interfaz donde revisas código.
Fundamentos de Workflows
Un workflow de GitHub Actions es un archivo YAML en .github/workflows/. Aquí hay un workflow mínimo que ejecuta tests en cada push:
name: Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm test
Triggers
GitHub Actions soporta muchos eventos trigger:
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * *' # Diario a las 6 AM UTC
workflow_dispatch: # Trigger manual desde UI
Para QA, los triggers más importantes son:
- pull_request: Ejecutar tests en cada PR para detectar problemas antes del merge
- push a main: Ejecutar regresión completa después del merge para verificar la rama principal
- schedule: Suites de tests nocturnos completos, tests de performance o escaneos de seguridad
Jobs y Steps
Un workflow contiene uno o más jobs. Cada job se ejecuta en una máquina virtual limpia (runner). Los jobs se ejecutan en paralelo por defecto pero pueden depender entre sí:
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run test:unit
e2e-tests:
needs: unit-tests # Se ejecuta después de que unit-tests complete
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
Estrategia Matrix para Testing Cross-Browser
Las estrategias matrix son una de las funcionalidades más poderosas de GitHub Actions para QA. Te permiten ejecutar la misma suite de tests en múltiples configuraciones automáticamente:
jobs:
e2e-tests:
strategy:
matrix:
browser: [chromium, firefox, webkit]
os: [ubuntu-latest, windows-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx playwright install --with-deps ${{ matrix.browser }}
- run: npx playwright test --project=${{ matrix.browser }}
Esto crea 6 jobs paralelos (3 navegadores x 2 sistemas operativos). Configurar fail-fast: false asegura que todas las combinaciones se ejecuten incluso si una falla — quieres conocer todos los fallos, no solo el primero.
Sharding de Suites de Tests Grandes
Para suites de tests grandes, puedes dividir tests entre múltiples runners:
jobs:
e2e-tests:
strategy:
matrix:
shard: [1, 2, 3, 4]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test --shard=${{ matrix.shard }}/4
Esto divide la suite de tests en 4 partes iguales ejecutándose en paralelo. Una suite de 40 minutos se convierte en 10 minutos.
Artefactos y Reportes de Tests
Subiendo Artefactos de Tests
Guarda reportes de tests, capturas de pantalla y videos de las ejecuciones:
- name: Ejecutar tests E2E
run: npx playwright test
continue-on-error: true
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: |
playwright-report/
test-results/
retention-days: 14
La condición if: always() asegura que los artefactos se suban incluso cuando los tests fallan — es cuando más los necesitas.
Publicando Resultados de Tests en PRs
Usa acciones de terceros para publicar resultados de tests como comentarios en PRs:
- name: Publicar Resultados de Tests
uses: dorny/test-reporter@v1
if: always()
with:
name: Tests Playwright
path: test-results/junit.xml
reporter: java-junit
Esto crea un check run con resultados detallados de tests visibles directamente en el pull request.
Caché para Builds más Rápidos
Cachear dependencias reduce dramáticamente el tiempo del pipeline:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
# Para navegadores de Playwright
- name: Cachear navegadores Playwright
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Instalar Playwright
run: npx playwright install --with-deps
Sin caché, npm ci y la instalación de navegadores pueden tomar 2-3 minutos. Con caché, toman segundos.
Secrets y Variables de Entorno
jobs:
test:
runs-on: ubuntu-latest
env:
BASE_URL: https://staging.example.com
NODE_ENV: test
steps:
- run: npm run test:e2e
env:
API_KEY: ${{ secrets.STAGING_API_KEY }}
DB_URL: ${{ secrets.TEST_DATABASE_URL }}
Los secrets se configuran en los ajustes del repositorio (Settings > Secrets and variables > Actions). Se enmascaran en los logs y nunca se exponen en archivos de workflow.
Ejercicio: Construye un Workflow QA Completo
Crea un workflow de GitHub Actions que:
- Ejecute tests unitarios en cada push
- Ejecute tests E2E en 3 navegadores en pull requests
- Suba reportes de tests como artefactos
- Publique resultados de tests como check en PR
- Ejecute una regresión nocturna completa
Solución
name: QA Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run test:unit -- --coverage --ci
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
retention-days: 7
e2e-tests:
if: github.event_name == 'pull_request' || github.event_name == 'schedule'
needs: unit-tests
strategy:
matrix:
browser: [chromium, firefox, webkit]
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- name: Cachear Playwright
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: pw-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- run: npx playwright install --with-deps ${{ matrix.browser }}
- run: npx playwright test --project=${{ matrix.browser }}
env:
BASE_URL: ${{ secrets.STAGING_URL }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.browser }}
path: |
playwright-report/
test-results/
retention-days: 14
- name: Reporte de Tests
uses: dorny/test-reporter@v1
if: always()
with:
name: E2E ${{ matrix.browser }}
path: test-results/junit.xml
reporter: java-junit
nightly-regression:
if: github.event_name == 'schedule'
needs: e2e-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run test:regression
- run: npm run test:performance
Workflows Reutilizables
Si múltiples repositorios necesitan el mismo pipeline de tests, crea workflows reutilizables:
# .github/workflows/reusable-e2e.yml
name: E2E Tests Reutilizables
on:
workflow_call:
inputs:
base-url:
required: true
type: string
browsers:
required: false
type: string
default: '["chromium"]'
secrets:
api-key:
required: true
jobs:
e2e:
strategy:
matrix:
browser: ${{ fromJson(inputs.browsers) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright test --project=${{ matrix.browser }}
env:
BASE_URL: ${{ inputs.base-url }}
API_KEY: ${{ secrets.api-key }}
GitHub Actions vs Jenkins: Perspectiva QA
| Aspecto | GitHub Actions | Jenkins |
|---|---|---|
| Setup | Sin setup para repos de GitHub | Requiere instalación y mantenimiento del servidor |
| Costo | Gratis para repos públicos; minutos pagos para privados | Gratis pero pagas por servidores |
| Flexibilidad | Buena con acciones del marketplace | Máxima con más de 1800 plugins |
| Soporte containers | Docker nativo y service containers | Vía plugin Docker Pipeline |
| Integración PR | Nativa — checks, status, comentarios | Requiere plugins y webhooks |
| Self-hosted runners | Soportado | Funcionalidad core |
| Matrix builds | First-class con strategy.matrix | Requiere scripted pipeline |
| Gestión de secrets | Secrets de repositorio/org integrados | Plugin Credentials |
Mejores Prácticas
Usa
actions/checkout@v4confetch-depth: 0si tus tests dependen del historial de git (para detección de cambios o blame).Configura
fail-fast: falseen estrategias matrix para jobs de test. Quieres ver todos los fallos, no solo el primero.Cachea agresivamente — dependencias npm, navegadores de Playwright y cualquier otro recurso descargable.
Usa
continue-on-error: trueen steps de test combinado conif: always()en upload de artefactos. Esto asegura que los reportes de tests siempre estén disponibles.Fija versiones de acciones a hashes SHA específicos en producción, no solo versiones mayores. Esto previene ataques de cadena de suministro.
Usa grupos de concurrencia para cancelar ejecuciones de workflow obsoletas cuando se pushea un nuevo commit:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true