Elysia Tools
Navigation mobile
Testing
GitHub Actions Testing - Intégration CI/CD
Workflows complets de test GitHub Actions incluant tests automatisés, exécution parallèle, rapports de tests, mise en cache et patterns CI/CD avancés pour pipelines de développement modernes
Exemples
Entrées de cette collection
Configuration de Base des Tests GitHub Actions
Configuration complète des tests GitHub Actions avec workflows de base, exécution des tests, rapports et intégration CI/CD
Difficulté
3/10
Temps estimé
40 min
Étiquettes
github actions, ci cd, setup, workflows
Prérequis
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,
};Patterns Avancés de Tests GitHub Actions
Patterns CI/CD complexes incluant builds matriciels, stratégies de cache, parallélisation des tests, exécution conditionnelle et optimisation de workflows au niveau entreprise
Difficulté
8/10
Temps estimé
90 min
Étiquettes
github actions, advanced, matrix, caching, optimization
Prérequis
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 }}Outils
Outils souvent utilisés avec cet exemple
Associé