Elysia Tools
Navegación
Testing
GitHub Actions Testing - Integración CI/CD
Flujos de trabajo completos de prueba de GitHub Actions incluyendo pruebas automatizadas, ejecución paralela, reportes de pruebas, caching y patrones CI/CD avanzados para pipelines de desarrollo modernos
Ejemplos
Entradas de esta colección
Configuración Básica de Pruebas con GitHub Actions
Configuración completa de pruebas con GitHub Actions con workflows básicos, ejecución de pruebas, reportes e integración CI/CD
Dificultad
3/10
Tiempo estimado
40 min
Etiquetas
github actions, ci cd, setup, workflows
Requisitos previos
Git basics, CI/CD concepts, YAML, JavaScript/TypeScript
# GitHub Actions Testing - Basic Setup and Configuration
# 1. .github/workflows/test.yml - Basic Testing Workflow
name: Tests
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
NODE_VERSION: '18'
NODE_OPTIONS: '--max-old-space-size=4096'
jobs:
# Unit Tests
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:unit
- name: Upload coverage reports
if: matrix.node-version == '18'
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella
# Integration Tests
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test_db
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Setup test environment
run: |
cp .env.test .env
npm run db:migrate
- name: Run integration tests
run: npm run test:integration
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
REDIS_URL: redis://localhost:6379
# End-to-End Tests
e2e-tests:
name: E2E Tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Build application
run: npm run build
- name: Run E2E tests
run: npm run test:e2e
- name: Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
# 2. .github/workflows/quality.yml - Code Quality Checks
name: Code Quality
on:
pull_request:
branches: [ main ]
jobs:
lint:
name: Lint Code
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run Prettier check
run: npm run format:check
- name: Type checking
run: npm run type-check
security:
name: Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Run security audit
run: npm audit --audit-level=moderate
- name: Run Snyk security scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
# 3. .github/workflows/performance.yml - Performance Testing
name: Performance Tests
on:
schedule:
- cron: '0 2 * * *' # Run daily at 2 AM UTC
workflow_dispatch:
jobs:
lighthouse:
name: Lighthouse Performance Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Run Lighthouse CI
run: |
npm install -g @lhci/cli@0.12.x
lhci autorun
env:
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
load-testing:
name: Load Testing
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install k6
run: |
sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6
- name: Run load tests
run: k6 run --out json=results.json tests/performance/load-test.js
- name: Upload results
uses: actions/upload-artifact@v3
with:
name: load-test-results
path: results.json
# 4. package.json scripts configuration
{
"name": "example-project",
"version": "1.0.0",
"scripts": {
"test": "npm run test:unit && npm run test:integration && npm run test:e2e",
"test:unit": "jest",
"test:unit:watch": "jest --watch",
"test:unit:coverage": "jest --coverage",
"test:integration": "jest --config=jest.integration.config.js",
"test:e2e": "playwright test",
"test:e2e:headed": "playwright test --headed",
"test:e2e:debug": "playwright test --debug",
"lint": "eslint src/**/*.js tests/**/*.js",
"lint:fix": "eslint src/**/*.js tests/**/*.js --fix",
"format": "prettier --write src/**/* tests/**/*",
"format:check": "prettier --check src/**/* tests/**/*",
"type-check": "tsc --noEmit",
"build": "tsc && npm run build:assets",
"build:assets": "cp -r src/public dist/",
"dev": "npm run build && node dist/index.js",
"db:migrate": "sequelize-cli db:migrate",
"db:seed": "sequelize-cli db:seed:all"
},
"devDependencies": {
"@playwright/test": "^1.40.0",
"@lhci/cli": "^0.12.0",
"eslint": "^8.55.0",
"prettier": "^3.1.0",
"jest": "^29.7.0",
"jest-environment-node": "^29.7.0",
"snyk": "^1.1291.0"
}
}
# 5. .github/workflows/notify.yml - Test Result Notifications
name: Test Notifications
on:
workflow_run:
workflows: ["Tests"]
types:
- completed
jobs:
notify:
name: Send Notifications
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: Send Slack notification
uses: 8398a7/action-slack@v3
with:
status: failure
channel: '#dev-alerts'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
text: |
Tests failed for ${{ github.repository }}
Branch: ${{ github.ref }}
Commit: ${{ github.sha }}
View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
- name: Send email notification
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 587
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
subject: "Test Failed - ${{ github.repository }}"
body: |
Tests failed for ${{ github.repository }}
Branch: ${{ github.ref }}
Commit: ${{ github.sha }}
Author: ${{ github.event.head_commit.author.name }}
View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
to: ${{ secrets.NOTIFICATION_EMAIL }}
from: GitHub Actions
# 6. .github/workflows/release.yml - Release Testing
name: Release
on:
release:
types: [published]
jobs:
release-tests:
name: Pre-release Testing
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run full test suite
run: npm run test
- name: Build release
run: npm run build
- name: Run smoke tests
run: npm run test:smoke
- name: Upload release artifacts
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./dist/app.zip
asset_name: app-v${{ github.event.release.tag_name }}.zip
asset_content_type: application/zip
# 7. jest.config.js - Jest Configuration for CI
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
roots: ['<rootDir>/src', '<rootDir>/tests'],
testMatch: [
'**/__tests__/**/*.+(ts|tsx|js)',
'**/*.(test|spec).+(ts|tsx|js)'
],
transform: {
'^.+\.(ts|tsx)$': 'ts-jest',
},
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*.d.ts',
'!src/index.ts',
],
coverageDirectory: 'coverage',
coverageReporters: [
'text',
'lcov',
'html',
'json'
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
},
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
testTimeout: 30000,
};Patrones Avanzados de Pruebas con GitHub Actions
Patrones CI/CD complejos incluyendo construcciones matriciales, estrategias de caching, paralelización de pruebas, ejecución condicional y optimización de workflows a nivel empresarial
Dificultad
8/10
Tiempo estimado
90 min
Etiquetas
github actions, advanced, matrix, caching, optimization
Requisitos previos
GitHub Actions basics, CI/CD advanced, YAML, DevOps concepts
# GitHub Actions Advanced Testing Patterns
# 1. .github/workflows/matrix-testing.yml - Advanced Matrix Strategy
name: Matrix Testing
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# Matrix strategy for multiple environments
test-matrix:
name: Test (${{ matrix.os }}, Node ${{ matrix.node-version }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16, 18, 20]
include:
- os: ubuntu-latest
node-version: 20
coverage: true
- os: windows-latest
node-version: 18
edge-cases: true
- os: macos-latest
node-version: 16
browser-tests: true
exclude:
- os: windows-latest
node-version: 16
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node-version }}-
- name: Install browsers
if: matrix.browser-tests
run: npx playwright install chromium firefox webkit
- name: Run unit tests
run: npm run test:unit
- name: Run tests with coverage
if: matrix.coverage
run: npm run test:coverage
- name: Run edge case tests
if: matrix.edge-cases
run: npm run test:edge-cases
- name: Run browser tests
if: matrix.browser-tests
run: npm run test:browser
- name: Upload coverage to Codecov
if: matrix.coverage && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v3
with:
file: ./coverage/lcov.info
flags: ${{ matrix.os }}-node${{ matrix.node-version }}
name: codecov-${{ matrix.os }}-${{ matrix.node-version }}
# Parallel execution with test splitting
parallel-tests:
name: Parallel Tests (Shard ${{ matrix.shard }}/${{ strategy.job-total }})
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Split tests
id: split-tests
run: |
# Get total number of tests and split them
TEST_FILES=$(npm run test:list 2>/dev/null | grep -E "\.test\.|\.spec\." | wc -l)
echo "total-tests=$TEST_FILES" >> $GITHUB_OUTPUT
# Calculate which tests to run for this shard
SHARD_SIZE=$((TEST_FILES / 4 + 1))
START=$(((matrix.shard - 1) * SHARD_SIZE + 1))
END=$((matrix.shard * SHARD_SIZE))
echo "start=$START" >> $GITHUB_OUTPUT
echo "end=$END" >> $GITHUB_OUTPUT
- name: Run shard tests
run: |
npm run test:shard -- --shard=${{ matrix.shard }}/4
- name: Upload test results
uses: actions/upload-artifact@v3
with:
name: test-results-shard-${{ matrix.shard }}
path: test-results/
# 2. .github/workflows/conditional-testing.yml - Conditional Execution
name: Conditional Testing
on:
push:
branches: [ main ]
pull_request:
types: [opened, synchronize, reopened]
jobs:
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
outputs:
backend-changed: ${{ steps.changes.outputs.backend }}
frontend-changed: ${{ steps.changes.outputs.frontend }}
docs-changed: ${{ steps.changes.outputs.docs }}
all-changed: ${{ steps.changes.outputs.all }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Detect file changes
id: changes
uses: dorny/paths-filter@v2
with:
filters: |
backend:
- 'src/backend/**'
- 'package.json'
frontend:
- 'src/frontend/**'
- 'public/**'
docs:
- 'docs/**'
- '**/*.md'
all:
- '**'
# Conditional job execution
backend-tests:
name: Backend Tests
needs: detect-changes
if: needs.detect-changes.outputs.backend-changed == 'true'
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run backend tests
run: |
npm run test:backend
npm run test:api
- name: Run integration tests
run: npm run test:integration
frontend-tests:
name: Frontend Tests
needs: detect-changes
if: needs.detect-changes.outputs.frontend-changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Build application
run: npm run build:frontend
- name: Run frontend tests
run: npm run test:frontend
- name: Run E2E tests
run: npm run test:e2e
full-suite:
name: Full Test Suite
needs: detect-changes
if: |
needs.detect-changes.outputs.all-changed == 'true' ||
github.event_name == 'schedule' ||
contains(github.event.head_commit.message, '[full-test]')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run complete test suite
run: npm run test:all
# 3. .github/workflows/caching-optimization.yml - Advanced Caching
name: Optimized Testing with Caching
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test-with-caching:
name: Tests with Advanced Caching
runs-on: ubuntu-latest
env:
CACHE_VERSION: v2
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Cache node modules
id: cache-node
uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
key: ${{ env.CACHE_VERSION }}-npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ env.CACHE_VERSION }}-npm-${{ runner.os }}-
- name: Install dependencies
if: steps.cache-node.outputs.cache-hit != 'true'
run: npm ci
- name: Cache build artifacts
id: cache-build
uses: actions/cache@v3
with:
path: |
dist/
.next/
build/
key: ${{ env.CACHE_VERSION }}-build-${{ github.sha }}
restore-keys: |
${{ env.CACHE_VERSION }}-build-
- name: Build application
if: steps.cache-build.outputs.cache-hit != 'true'
run: npm run build
- name: Cache Playwright browsers
uses: actions/cache@v3
with:
path: ~/.cache/ms-playwright
key: ${{ env.CACHE_VERSION }}-playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Cache test database
uses: actions/cache@v3
with:
path: |
test-data/
fixtures/
key: ${{ env.CACHE_VERSION }}-test-data-${{ hashFiles('test-data/**') }}
- name: Setup test database
run: |
npm run db:setup
npm run db:seed
- name: Run tests
run: npm run test
- name: Cache test results
uses: actions/cache@v3
with:
path: |
coverage/
test-results/
playwright-report/
key: ${{ env.CACHE_VERSION }}-test-results-${{ github.sha }}
# 4. .github/workflows/reusable-workflows.yml - Reusable Workflows
# This file defines reusable workflows that can be called from other workflows
# .github/workflows/test-reusable.yml
name: Reusable Test Workflow
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '18'
test-type:
required: false
type: string
default: 'all'
cache-key:
required: false
type: string
default: 'default'
secrets:
NPM_TOKEN:
required: false
CODECOV_TOKEN:
required: false
jobs:
run-tests:
name: Tests (${{ inputs.test-type }})
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Configure private registry
if: secrets.NPM_TOKEN
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc
echo "@example:registry=https://npm.example.com" >> ~/.npmrc
- name: Run tests based on type
run: |
case "${{ inputs.test-type }}" in
"unit")
npm run test:unit
;;
"integration")
npm run test:integration
;;
"e2e")
npm run test:e2e
;;
"all")
npm run test
;;
esac
- name: Upload coverage
if: inputs.test-type != 'e2e' && secrets.CODECOV_TOKEN
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: ${{ inputs.test-type }}
# .github/workflows/main.yml - Using reusable workflow
name: Main Testing Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
unit-tests:
uses: ./.github/workflows/test-reusable.yml
with:
node-version: '18'
test-type: 'unit'
cache-key: 'unit-tests'
integration-tests:
uses: ./.github/workflows/test-reusable.yml
with:
node-version: '18'
test-type: 'integration'
cache-key: 'integration-tests'
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
e2e-tests:
uses: ./.github/workflows/test-reusable.yml
with:
node-version: '20'
test-type: 'e2e'
cache-key: 'e2e-tests'
# 5. .github/workflows/test-metrics.yml - Test Metrics and Reporting
name: Test Metrics and Reporting
on:
workflow_run:
workflows: ["Tests"]
types:
- completed
jobs:
generate-report:
name: Generate Test Report
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion != 'skipped' }}
steps:
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: test-results
path: ./test-results
- name: Generate test report
run: |
# Create comprehensive test report
node scripts/generate-test-report.js
- name: Update PR comment with results
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const report = JSON.parse(fs.readFileSync('./test-report.json', 'utf8'));
const comment = `## Test Results
**Total Tests:** ${report.total}
**Passed:** ${report.passed} ✅
**Failed:** ${report.failed} ❌
**Skipped:** ${report.skipped} ⏭️
**Coverage:** ${report.coverage}%
[View detailed report](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
- name: Update test metrics
run: |
# Update metrics in external system
node scripts/update-metrics.js
- name: Create test summary
id: test-summary
run: |
# Create markdown summary
echo "summary<<EOF" >> $GITHUB_OUTPUT
cat test-summary.md >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Comment on PR
uses: peter-evans/create-or-update-comment@v3
if: github.event_name == 'pull_request'
with:
issue-number: ${{ github.event.pull_request.number }}
body: ${{ steps.test-summary.outputs.summary }}Herramientas
Herramientas que suelen usarse con este ejemplo
Relacionado