playwright.config.ts define o timeout dos testes, contagem de retries, workers paralelos, comportamento de trace e baseURL para toda a suite. Os padrões gerados pelo npm init playwright@latest funcionam localmente, mas têm dois problemas no CI. workers: undefined causa contenção de recursos em runners compartilhados, e a ausência de forbidOnly: !!process.env.CI permite que um test.only() commitado pule silenciosamente a suite inteira.
O config mínimo
Após npm init playwright@latest, você recebe algo assim:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
});Vamos detalhar cada seção.
Opções de nível superior
testDir
Onde o Playwright procura arquivos de teste.
testDir: './tests',Pode ser um caminho relativo ou absoluto. Arquivos que correspondem a /.spec.ts ou /.test.ts dentro dessa pasta são detectados automaticamente.
fullyParallel
fullyParallel: true,Quando true: todos os testes rodam em paralelo entre workers, inclusive testes no mesmo arquivo.
Quando false (padrão anterior): testes dentro de um arquivo rodam em sequência, mas arquivos diferentes rodam em paralelo.
Para a maioria dos projetos: use true. Os testes devem ser independentes o suficiente para rodar em qualquer ordem.
forbidOnly
forbidOnly: !!process.env.CI,Se um teste tiver test.only(), isso faz o run inteiro falhar. O padrão !!process.env.CI significa que só é enforçado no CI, então você pode usar test.only() localmente durante o debug, mas não pode commitar acidentalmente.
Sempre use isso em configs de produção.
retries
retries: process.env.CI ? 2 : 0,Quantas vezes tentar um teste que falhou antes de marcá-lo como falha definitiva. No CI: tenta mais duas vezes (ajuda com testes flaky). Localmente: sem retries (você vê as falhas imediatamente).
Se um teste falha na primeira tentativa mas passa no retry, o Playwright o marca como "flaky" no relatório.
workers
workers: process.env.CI ? 1 : undefined,Quantos workers paralelos (instâncias de navegador) rodar.
undefined(padrão): usa 50% dos núcleos de CPU1: roda todos os testes em sequência, útil no CI para evitar contenção de recursos4: roda 4 workers em paralelo
No desenvolvimento local com uma máquina rápida, undefined funciona bem. No CI, 1 é mais seguro a menos que você tenha um runner potente.
timeout
timeout: 30_000, // 30 segundos por testeTempo máximo que um único teste pode rodar antes de ser marcado como falha. O padrão é 30 segundos. Para testes lentos ou máquinas de CI lentas, aumente para 60 segundos.
expect.timeout
expect: {
timeout: 5_000, // 5 segundos para cada assertion expect()
},As assertions do Playwright fazem retry automático: continuam tentando até a condição ser atendida ou esse timeout expirar. O padrão é 5 segundos.
O bloco use (opções compartilhadas de teste)
use contém opções que se aplicam a todos os testes (a menos que sejam sobrescritas por um projeto).
use: {
baseURL: 'http://localhost:3000',
// Configurações do navegador
headless: true,
viewport: { width: 1280, height: 720 },
// Gravação
trace: 'on-first-retry', // 'on-first-retry' | 'retain-on-failure' | 'always' | 'off'
video: 'retain-on-failure', // 'retain-on-failure' | 'always' | 'off'
screenshot: 'only-on-failure',
// Timeouts
actionTimeout: 10_000, // Timeout para cada ação (click, fill, etc.)
navigationTimeout: 30_000, // Timeout para page.goto() e page.waitForURL()
// HTTP
ignoreHTTPSErrors: true, // Útil para ambientes de staging com certs autoassinados
// Locale
locale: 'pt-BR',
timezoneId: 'America/Sao_Paulo',
},baseURL
Quando definida, page.goto('/login') resolve para http://localhost:3000/login. Torna os testes portáveis entre ambientes.
Use variáveis de ambiente:
baseURL: process.env.BASE_URL || 'http://localhost:3000',trace
Os traces do Playwright capturam uma gravação completa de cada ação (snapshot do DOM, screenshots, chamadas de rede) para debug. Opções:
'on-first-retry'— captura no primeiro retry de um teste que falhou (recomendado)'retain-on-failure'— captura em qualquer teste que falhou (mais armazenamento)'always'— captura tudo (muito armazenamento, mais lento)'off'— sem traces
Para visualizar: npx playwright show-trace trace.zip.
video
'retain-on-failure'— salva vídeo só para testes que falharam (recomendado)'always'— salva vídeo de tudo'off'— sem vídeo
projects — Múltiplas configurações de navegador
Projects permitem rodar os mesmos testes em navegadores, viewports ou configurações diferentes.
projects: [
// Navegadores desktop
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
// Mobile
{
name: 'mobile-chrome',
use: { ...devices['Pixel 7'] },
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 14'] },
},
],devices['Desktop Chrome'] é um preset que define viewport, user agent e outros padrões específicos do navegador. Lista completa: npx playwright show-report ou a documentação do Playwright.
Projects para ambientes diferentes
projects: [
{
name: 'staging',
use: {
...devices['Desktop Chrome'],
baseURL: 'https://staging.myapp.com',
},
testMatch: '**/*.spec.ts',
},
{
name: 'production',
use: {
...devices['Desktop Chrome'],
baseURL: 'https://myapp.com',
},
testMatch: '**/smoke/*.spec.ts', // Só smoke tests em produção
},
],Setup projects (setup global)
projects: [
{
name: 'setup',
testMatch: /.*\.setup\.ts/, // Arquivos como auth.setup.ts
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['setup'], // Roda o setup primeiro
},
],Usado para rodar o setup de autenticação uma vez antes de todos os testes e reutilizar o estado de auth salvo.
reporter
Em que formato gerar os resultados dos testes:
reporter: [
['html'], // Relatório HTML em playwright-report/
['junit', { outputFile: 'results.xml' }], // JUnit XML para CI
['list'], // Output ao vivo no console
],Para desenvolvimento local: 'html' é ótimo. Abra playwright-report/index.html para um relatório visual completo.
Para CI: adicione 'junit' para que ferramentas de CI (GitHub Actions, GitLab CI, Jenkins) consigam parsear os resultados.
globalSetup e globalTeardown
Para setup que roda uma vez antes de toda a suite de testes começar:
globalSetup: './global-setup.ts',
globalTeardown: './global-teardown.ts',// global-setup.ts
import { chromium } from '@playwright/test';
export default async function globalSetup() {
const browser = await chromium.launch();
const page = await browser.newPage();
// Faz login e salva o estado de auth
await page.goto('http://localhost:3000/login');
await page.fill('[data-testid="email"]', 'admin@test.com');
await page.fill('[data-testid="password"]', 'AdminPass1');
await page.click('[data-testid="submit"]');
await page.context().storageState({ path: 'auth.json' });
await browser.close();
}Os testes passam a usar o estado de auth salvo sem precisar logar novamente:
use: {
storageState: 'auth.json',
},Um config pronto para produção
import { defineConfig, devices } from '@playwright/test';
import dotenv from 'dotenv';
dotenv.config();
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 2 : undefined,
timeout: 45_000,
expect: { timeout: 8_000 },
reporter: [
['html'],
...(process.env.CI ? [['junit', { outputFile: 'test-results/results.xml' }] as const] : []),
],
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
trace: 'on-first-retry',
video: 'retain-on-failure',
screenshot: 'only-on-failure',
actionTimeout: 10_000,
navigationTimeout: 30_000,
},
projects: [
{
name: 'setup',
testMatch: /auth\.setup\.ts/,
},
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
storageState: 'playwright/.auth/user.json',
},
dependencies: ['setup'],
},
{
name: 'api',
testMatch: '**/api/**/*.spec.ts',
use: { storageState: undefined }, // Testes de API não precisam de auth de navegador
},
],
});Rodando projetos específicos
# Todos os testes no chromium
npx playwright test --project=chromium
# Só o projeto de setup
npx playwright test --project=setup
# Múltiplos projetos
npx playwright test --project=chromium --project=firefoxResumo das opções mais importantes
| Opção | Recomendação |
|--------|--------------|
| testDir | './tests' |
| fullyParallel | true |
| forbidOnly | !!process.env.CI |
| retries | CI ? 2 : 0 |
| timeout | 30_000–60_000 |
| trace | 'on-first-retry' |
| video | 'retain-on-failure' |
| baseURL | A partir de variável de ambiente |
| reporter | HTML localmente, + JUnit no CI |
Vale dedicar 30 minutos para acertar o config no início do projeto. Um playwright.config.ts bem configurado economiza horas de debug e troubleshooting no CI.