E2E com Playwright
Testes de ponta a ponta que rodam no browser real. Flaky-free com auto-wait e locators.
Definição
Playwright é a ferramenta líder de testes E2E em 2025: multi-browser (Chrome, Firefox, WebKit), auto-wait nativo (não precisa de sleep/waitFor manuais), locators que imitam RTL (getByRole, getByLabel), e um modo de debug visual excelente (UI mode, trace viewer). Testa o sistema completo: frontend + API real ou mockada.
Problema → Solução
Problema
Testes E2E flaky por races de timing (await sleep(1000)), seletores frágeis (CSS classes que mudam), e não saber onde está o bug quando o teste falha.Solução
Auto-wait do Playwright: toda action aguarda o elemento estar pronto. Locators semânticos (getByRole) em vez de CSS. Trace viewer para debug: gravação completa do teste com screenshots, network e console. Page Object Model para organizar seletores reutilizáveis.Dica de entrevista
Tip
Não teste tudo com E2E — é o topo da pirâmide. E2E para fluxos críticos de negócio: login, checkout, onboarding. Para componentes isolados: RTL. Para API: testes de integração. A regra: se quebrar isso, a empresa perde dinheiro → E2E. Se não → RTL ou unitário.Código
// tests/login.spec.ts
import { test, expect } from '@playwright/test'
test('fluxo de login completo', async ({ page }) => {
await page.goto('/login')
// Locators semânticos — como RTL
await page.getByLabel('Email').fill('user@test.com')
await page.getByLabel('Senha').fill('secret123')
await page.getByRole('button', { name: 'Entrar' }).click()
// Auto-wait — sem sleep, sem waitFor manual
await expect(page).toHaveURL('/dashboard')
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible()
})
// Mock de API com page.route()
test('mostra erro quando API falha', async ({ page }) => {
await page.route('/api/auth', route =>
route.fulfill({ status: 401, body: 'Unauthorized' })
)
await page.goto('/login')
await page.getByRole('button', { name: 'Entrar' }).click()
await expect(page.getByRole('alert')).toContainText('Email ou senha inválidos')
})
// Page Object Model
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()
}
}Perguntas de entrevista
Q.Playwright vs Cypress: qual escolher em 2025?▾
A.Playwright: multi-browser real, mais rápido, melhor para apps React/Next.js modernos, auto-wait mais confiável, gratuito sem limitações. Cypress: melhor DX para debug em tempo real (vê o app enquanto o teste roda), hot reload, mais fácil para iniciantes. Para projetos novos: Playwright. Para times já em Cypress: não migrate sem necessidade.
Q.Como evitar testes flaky no Playwright?▾
A.Nunca use page.waitForTimeout(n) — use locators com auto-wait. Nunca confie em animações concluídas — await expect(locator).toBeVisible(). Para network: use page.waitForResponse() ou mock com page.route(). Isole o estado: cada teste começa limpo (beforeEach com login via API, não UI).
Q.O que é Page Object Model?▾
A.Padrão para encapsular seletores e ações de uma página em uma classe. Em vez de page.locator('.login-btn') espalhado nos testes, você cria LoginPage com loginPage.submit(). Facilita manutenção: quando o seletor muda, muda em um lugar só.
74/122← →