Um passo de upload sem if: always() é ignorado quando os testes falham, deixando você sem relatório HTML e sem screenshots exatamente no momento em que você mais precisa. O relatório de testes no CI tem três camadas: artefatos para inspeção, JUnit XML para parsing nos dashboards, e comentários de PR que mostram as falhas onde os desenvolvedores olham.
O problema com o output bruto de testes
O output padrão do CI para uma execução Playwright com falha parece assim:
✘ tests/login.spec.ts > mostra erro para senha errada (15234ms)
Error: Timed out 5000ms waiting for expect(locator).toBeVisible()
Call log:
- expect.toBeVisible with timeout 5000ms
- waiting for locator('[data-testid="error-message"]')Você tem que ler centenas de linhas de output para encontrar as falhas. Numa suite de 200 testes, isso é doloroso.
Formatos de relatório
JUnit XML
O formato universal: todo sistema de CI entende.
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="Login Tests" tests="5" failures="1" time="12.5">
<testcase name="mostra erro para senha errada" time="15.2">
<failure message="Timed out waiting for error-message">
Error: Timed out 5000ms waiting for expect(locator).toBeVisible()
...
</failure>
</testcase>
<testcase name="login bem-sucedido redireciona para dashboard" time="3.2" />
</testsuite>
</testsuites>// playwright.config.ts
reporter: [
['junit', { outputFile: 'test-results/results.xml' }],
['list'], // Mostrar também no console
],Relatório HTML
O relatório HTML integrado do Playwright: visual, com screenshots e traces.
reporter: [
['html', { outputFolder: 'playwright-report', open: 'never' }],
],Gerar e abrir localmente:
npx playwright show-reportJSON
Formato legível por máquina para processamento customizado:
reporter: [
['json', { outputFile: 'test-results/results.json' }],
],Útil para construir dashboards customizados ou parsear resultados programaticamente.
Múltiplos reporters
Geralmente você quer vários formatos:
reporter: process.env.CI
? [
['junit', { outputFile: 'test-results/results.xml' }],
['html', { outputFolder: 'playwright-report', open: 'never' }],
['list'], // Output ao vivo nos logs do CI
]
: [
['html'], // Local: apenas o relatório visual
['list'],
],Integração com GitHub Actions
Configuração básica com upload de artefatos
name: Playwright Tests
on: [push, pull_request]
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: npx playwright install --with-deps chromium
- name: Rodar testes
run: npx playwright test
env:
BASE_URL: ${{ secrets.STAGING_URL }}
# Sempre fazer upload do relatório, mesmo quando os testes falham
- name: Upload relatório HTML
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- name: Upload resultados JUnit
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: test-results/results.xmlO if: always() é crítico: sem ele, o passo de upload é ignorado quando os testes falham.
Anotações de teste JUnit no GitHub
O GitHub Actions consegue parsear JUnit XML e anotar o seu PR com falhas diretamente no diff:
- name: Reportar resultados dos testes
uses: dorny/test-reporter@v1
if: always()
with:
name: Playwright Tests
path: test-results/results.xml
reporter: java-junit
fail-on-error: trueIsso mostra um resumo na interface do GitHub PR e anota os testes com falha no código.
Integração com GitLab CI
O GitLab tem suporte nativo a JUnit:
test:
image: mcr.microsoft.com/playwright:v1.44.0-jammy
script:
- npm ci
- npx playwright test
artifacts:
when: always
reports:
junit: test-results/results.xml # Suporte nativo a JUnit
paths:
- playwright-report/ # Upload do relatório HTML também
expire_in: 1 weekO GitLab lê o JUnit XML e mostra um resumo de testes na UI do pipeline, sem ferramentas extras.
Notificações no Slack
Envie resumos de falhas para o Slack quando os testes do CI falham:
- name: Notificar Slack em caso de falha
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "❌ Testes Playwright falharam em ${{ github.ref_name }}",
"attachments": [{
"color": "danger",
"fields": [
{
"title": "Branch",
"value": "${{ github.ref_name }}",
"short": true
},
{
"title": "Execução",
"value": "${{ github.run_id }}",
"short": true
},
{
"title": "Relatório",
"value": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
]
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}Parsing de resultados programaticamente
Às vezes você precisa de lógica customizada: notificar apenas em novas falhas, não em re-falhas:
// scripts/parse-results.js
const fs = require('fs');
const xml2js = require('xml2js');
async function parseResults() {
const xml = fs.readFileSync('test-results/results.xml', 'utf8');
const result = await xml2js.parseStringPromise(xml);
const testsuites = result.testsuites.testsuite;
const failures = [];
testsuites.forEach(suite => {
(suite.testcase || []).forEach(testcase => {
if (testcase.failure) {
failures.push({
name: testcase.$.name,
suite: suite.$.name,
message: testcase.failure[0].$.message,
time: testcase.$.time,
});
}
});
});
console.log(`Total de falhas: ${failures.length}`);
failures.forEach(f => {
console.log(`- [${f.suite}] ${f.name}`);
console.log(` ${f.message}`);
});
process.exit(failures.length > 0 ? 1 : 0);
}
parseResults();Comentário de resumo de testes nos PRs
Comente automaticamente um resumo de testes em cada PR:
- name: Comentário de resumo de testes
uses: marocchino/sticky-pull-request-comment@v2
if: always()
with:
header: test-results
message: |
## Resultados dos Testes
${{ steps.test-results.outputs.summary }}
[Ver relatório completo](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})Retenção e histórico
Resultados brutos só são úteis se você os mantém por tempo suficiente.
GitHub Actions:- uses: actions/upload-artifact@v4
with:
retention-days: 30 # Manter por 30 dias- Allure TestOps: pago, mantém histórico ilimitado
- Bucket S3/GCS self-hosted: armazene results.json e gere relatórios de tendência
- Datadog ou Grafana: envie métricas das execuções de teste para dashboards
O que colocar em cada relatório de CI
Um relatório de testes útil responde:
1. Quantos testes passaram, falharam, foram ignorados? Contagens de resumo
2. Quais testes falharam? Lista completa de falhas com nomes dos testes
3. Por que falharam? Mensagens de erro e stack traces
4. Como está a aparência? Screenshots para testes de UI
5. Quanto tempo levou? Tempo de execução por teste
6. É uma nova falha? Comparação com a execução anterior
O relatório HTML do Playwright cobre de 1 a 5. Ferramentas de tendência (Allure, TestOps) adicionam o 6.
Resumo
| Formato | Melhor para |
|---------|-------------|
| JUnit XML | Integração com CI, anotações de PR |
| HTML | Leitura humana, screenshots, traces |
| JSON | Processamento customizado, dashboards |
| List | Output ao vivo no console |
Configuração mínima para CI:1. Gerar JUnit XML (o CI consegue parsear)
2. Fazer upload do relatório HTML como artefato
3. Usar if: always() nos passos de upload
- Relatório Allure com tendências
- Notificação no Slack em caso de falha
- Comentário de PR com resumo
- Anotação de teste na visualização do diff