R
Interview Deckreact · next.js · senior/staff
0·0·122
Testing

E2E com Playwright

Testes de ponta a ponta que rodam no browser real. Flaky-free com auto-wait e locators.

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
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.
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.
// 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()
  }
}
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← →