Playwright para testes E2E: configuração, boas práticas e CI
1. Introdução ao Playwright e Testes E2E
Testes End-to-End (E2E) simulam o comportamento real do usuário em uma aplicação, validando fluxos completos desde a interface até o backend. São críticos para garantir que funcionalidades críticas não sejam quebradas após deploys, especialmente em aplicações com múltiplas integrações.
O Playwright, desenvolvido pela Microsoft, destaca-se por oferecer suporte nativo a Chromium, Firefox e WebKit, executando testes em paralelo com alta velocidade. Diferente do Cypress, que opera exclusivamente no navegador Chromium, o Playwright permite testar em múltiplos motores de renderização com uma única API. Comparado ao Selenium, o Playwright elimina a necessidade de WebDrivers manuais, oferece auto-waiting inteligente e melhor performance em testes headless.
2. Configuração Inicial do Projeto
Para iniciar, instale o Playwright via npm:
npm init playwright@latest
O comando gera automaticamente a estrutura de diretórios:
project/
├── tests/
│ └── example.spec.ts
├── playwright.config.ts
├── package.json
└── node_modules/
Configure os navegadores e viewports no arquivo playwright.config.ts:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
retries: 2,
use: {
baseURL: 'http://localhost:3000',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
});
Estrutura de diretórios recomendada:
tests/
├── e2e/
│ ├── login.spec.ts
│ └── checkout.spec.ts
├── fixtures/
│ └── auth.fixture.ts
└── utils/
└── helpers.ts
3. Escrevendo Testes Robusto e Confiáveis
Priorize localizadores modernos que simulam a interação real do usuário:
// ✅ Recomendado: localizadores acessíveis
await page.getByRole('button', { name: 'Enviar' }).click();
await page.getByText('Bem-vindo').isVisible();
await page.getByTestId('user-profile').click();
// ❌ Evite: seletores frágeis
await page.$('#submit-btn');
await page.$('.container > div:nth-child(2)');
Use asserções inteligentes com polling automático:
await expect(page.getByRole('heading')).toHaveText('Dashboard');
await expect(page.getByTestId('loading-spinner')).not.toBeVisible();
await expect(page.locator('.error-message')).toHaveCount(0);
Evite waitForTimeout fixo. Prefira esperas condicionais:
// ✅ Correto: espera por URL específica
await page.waitForURL('**/dashboard');
// ✅ Correto: espera por elemento visível
await page.waitForSelector('[data-testid="user-table"]', { state: 'visible' });
// ❌ Incorreto: tempo fixo
await page.waitForTimeout(3000);
4. Gerenciamento de Estado e Fixtures
Reutilize sessões de autenticação para evitar login repetido:
// auth.fixture.ts
import { test as base } from '@playwright/test';
import path from 'path';
export const test = base.extend({
authenticatedPage: async ({ page, context }, use) => {
const storageState = path.resolve('./auth.json');
// Realiza login uma vez e salva o estado
await page.goto('/login');
await page.fill('[name="email"]', 'user@test.com');
await page.fill('[name="password"]', 'password123');
await page.click('button[type="submit"]');
await context.storageState({ path: storageState });
await use(page);
},
});
Mock de APIs para isolar dependências:
await page.route('**/api/users', async route => {
await route.fulfill({
status: 200,
body: JSON.stringify([{ id: 1, name: 'Mock User' }]),
});
});
5. Integração Contínua (CI) e Automação
Exemplo de pipeline GitHub Actions:
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
Para paralelismo e sharding:
npx playwright test --shard=1/4
npx playwright test --workers=4
Configure relatórios no playwright.config.ts:
reporter: [
['html'],
['json', { outputFile: 'test-results.json' }],
['allure-playwright'],
],
6. Manutenção e Boas Práticas Avançadas
Implemente Page Object Model simplificado:
// pages/LoginPage.ts
export class LoginPage {
constructor(private page: Page) {}
async login(email: string, password: string) {
await this.page.getByLabel('Email').fill(email);
await this.page.getByLabel('Senha').fill(password);
await this.page.getByRole('button', { name: 'Entrar' }).click();
}
async getErrorMessage() {
return this.page.getByTestId('error-message').textContent();
}
}
Trate flaky tests com retries e logging:
// playwright.config.ts
export default defineConfig({
retries: process.env.CI ? 2 : 0,
use: {
trace: 'retain-on-failure',
},
});
Para ambientes dinâmicos, use dados gerados automaticamente:
const uniqueEmail = `user_${Date.now()}@test.com`;
const today = new Date().toISOString().split('T')[0];
7. Monitoramento e Evolução Contínua
Integre com dashboards para visibilidade:
npx playwright show-report
Para feedback loop rápido, execute testes críticos localmente e testes completos em CI:
npm run test:critical # testes rápidos (1-2 min)
npm run test:full # todos os testes (10-15 min)
Próximos passos importantes:
- Testes visuais com
toMatchSnapshot():
await expect(page).toMatchSnapshot('homepage.png');
- Testes de acessibilidade com Axe:
import { injectAxe, checkA11y } from 'axe-playwright';
await injectAxe(page);
await checkA11y(page);
Referências
- Documentação Oficial do Playwright — Guia completo de instalação, API e boas práticas para testes E2E modernos.
- Playwright vs Cypress vs Selenium — Comparação detalhada das principais ferramentas de automação de testes.
- Testes E2E com Playwright e GitHub Actions — Tutorial oficial da Microsoft para integração contínua com Playwright.
- Playwright: Boas Práticas de Localizadores — Documentação sobre seletores modernos e estratégias de localização de elementos.
- Allure Framework com Playwright — Guia para integração de relatórios visuais e dashboards de testes.
- Testes de Acessibilidade com Playwright e Axe — Como implementar testes automatizados de acessibilidade usando a biblioteca Axe-core.