CI/CD para QA: Automação do Pipeline de Testes

Testes Automatizados · 6 de julho de 2026

📖 5 min de leitura

O Que é CI/CD?

Continuous Integration (CI)

Desenvolvedores commitam código frequentemente (diariamente ou mais). Cada commit triggers build automático e suite de testes.

Continuous Delivery (CD)

Código que passa em todos os testes é automaticamente deployado para staging/produção.


GitHub Actions

Estrutura Básica

# .github/workflows/ci.yml
name: CI Pipeline

on:
push:
branches: [main, develop]
pull_request:
branches: [main]

env:
NODE_VERSION: '18'

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linter
run: npm run lint

- name: Run type check
run: npm run type-check

test:
needs: lint
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_DB: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

redis:
image: redis:7
ports:
- 6379:6379

steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run unit tests
run: npm run test:unit -- --coverage

- name: Run integration tests
env:
DATABASE_URL: postgresql://test:test@localhost:5432/test
REDIS_URL: redis://localhost:6379
run: npm run test:integration

- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
fail_ci_if_error: true

e2e:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push'

steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install dependencies
run: npm ci

- name: Install Playwright
run: npx playwright install --with-deps

- name: Run E2E tests
run: npm run test:e2e

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/

security:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run Snyk
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

- name: Run SonarCloud
uses: SonarSource/sonarcloud-github-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

deploy-staging:
needs: [test, security, e2e]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
environment: staging

steps:
- uses: actions/checkout@v4

- name: Deploy to Staging
run: |
echo "Deploying to staging..."
kubectl apply -f k8s/staging/

- name: Smoke tests
run: |
sleep 30
curl -f https://staging.exemplo.com/health

deploy-production:
needs: [deploy-staging]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production

steps:
- uses: actions/checkout@v4

- name: Deploy to Production
run: |
echo "Deploying to production..."
kubectl apply -f k8s/production/


GitLab CI

# .gitlab-ci.yml
stages:
  - lint
  - test
  - security
  - deploy

variables:
NODE_VERSION: '18'
POSTGRES_DB: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test

lint:
stage: lint
image: node:$NODE_VERSION
before_script:
- npm ci
script:
- npm run lint
- npm run type-check
allow_failure: false

test:unit:
stage: test
image: node:$NODE_VERSION
services:
- postgres:15
before_script:
- npm ci
script:
- npm run test:unit -- --coverage
coverage: '/Liness:s(d+.d+){6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}/'
artifacts:
reports:
junit: junit.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml

test:integration:
stage: test
image: node:$NODE_VERSION
services:
- postgres:15
- redis:7
before_script:
- npm ci
script:
- npm run test:integration
dependencies:
- test:unit

test:e2e:
stage: test
image: node:$NODE_VERSION
before_script:
- npm ci
- npx playwright install --with-deps
script:
- npm run test:e2e
dependencies:
- test:integration
allow_failure: true

security:dependency-scanning:
stage: security
image: alpine:latest
before_script:
- apk add --no-cache curl
script:
- curl -sL https://getsentry.com/snippets/snyk-gitlab.sh | bash

deploy:staging:
stage: deploy
script:
- echo "Deploying to staging"
- kubectl config use-context staging
- kubectl apply -f k8s/staging/
environment:
name: staging
only:
- develop

deploy:production:
stage: deploy
script:
- echo "Deploying to production"
- kubectl config use-context production
- kubectl apply -f k8s/production/
environment:
name: production
when: manual
only:
- main


Quality Gates

Implementação

quality-gates:
  stage: quality
  image: node:$NODE_VERSION
  before_script:
    - npm ci
  script:
    - |
      # Check coverage
      COVERAGE=$(cat coverage/coverage.json | jq '.total.lines.pct')
      echo "Coverage: $COVERAGE{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}"

if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "Coverage below 80{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} threshold"
exit 1
fi

# Check test pass rate
PASS_RATE=$(cat test-results.json | jq '.passed / .total * 100')
echo "Pass rate: $PASS_RATE{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}"

if (( $(echo "$PASS_RATE < 95" | bc -l) )); then
echo "Pass rate below 95{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} threshold"
exit 1
fi

# Check security
if grep -q "high|critical" security-report.json; then
echo "Security vulnerabilities found"
exit 1
fi

echo "All quality gates passed"
needs:
- test
allow_failure: false


Test Reports

JUnit XML Format



  
  
    assert 'token' not in response
  

GitHub Actions Upload

- name: Upload JUnit test results
  uses: actions/upload-artifact@v4
  with:
    name: test-results
    path: test-results/junit.xml

  • name: Publish Test Results
uses: dorny/test-reporter@v1 with: name: Test Results path: test-results/*.xml reporter: java-junit fail-on: test failures

Conclusão

CI/CD robusto é essencial para QA moderno. As chaves são:

  1. Automação completa – Build, test, deploy
  2. Quality gates – Critérios objetivos para avançar
  3. Feedback rápido – Resultados em minutos
  4. Parallel execution – Speed up pipelines
  5. Reliable reporting – JUnit XML, cobertura, etc.