Seus testes Playwright passam: login clicado, dashboard renderizado, gráfico visível. Depois um cliente reporta que os números estão errados. A causa: a API retornou 200 OK com payload malformado, e sua suíte end-to-end só validava pixels na tela. Essa é a lacuna que testes de navegador não cobrem sozinhos. Ferramentas como o Apidog ajudam a validar contratos, schemas e semântica de respostas com o mesmo rigor aplicado aos fluxos de UI — e permitem executar essas validações junto com o Playwright na CI.
TL;DR
Combine o fixture request e o interceptor page.route do Playwright com cenários Apidog baseados na mesma especificação OpenAPI.
O fluxo recomendado:
- Use
openapi.yamlcomo contrato único. - Compartilhe fixtures entre Playwright e Apidog.
- Valide status, campos críticos e schemas.
- Use
page.routeapenas para isolamento da UI. - Execute Playwright e Apidog CLI no mesmo pipeline de CI.
Onde entram asserções de API em uma suíte Playwright
Um teste Playwright típico valida o comportamento visível:
await page.goto('/dashboard');
await expect(page.getByText('Pedidos')).toBeVisible();
await expect(page.getByTestId('chart')).toBeVisible();
Isso confirma que a UI renderizou. Não confirma que a API retornou dados corretos.
Problemas comuns que passam despercebidos:
- Campo renomeado de
total_countparatotalCount. - API retorna
200, mas com valores calculados incorretamente. - Branches de erro
400,401,409,429ou500nunca são exercitados. - Payloads opcionais ou enums mudam sem quebrar visualmente a tela.
A divisão prática fica assim:
- Playwright: fluxos de UI, ações do usuário, interceptação de rede e smoke checks de API próximos à interface.
- Apidog: contrato OpenAPI, validação de schema, cenários encadeados, mocks e caminhos de erro.
Para uma abordagem contract-first mais ampla, veja o guia sobre fluxos de trabalho de API design-first.
Estrutura recomendada do projeto
Use uma única especificação como fonte de verdade:
.
├── openapi.yaml
├── fixtures/
│ └── order.json
├── tests/
│ ├── fixtures/
│ │ └── api.ts
│ └── orders.spec.ts
├── apidog/
│ └── scenarios/
│ └── checkout.json
└── playwright.config.ts
O objetivo é simples: o mesmo contrato e os mesmos dados de teste alimentam Playwright e Apidog.
Criando um fixture de API para Playwright
Crie um fixture reutilizável para autenticação, contexto de API e payloads compartilhados.
// tests/fixtures/api.ts
import { test as base, APIRequestContext, expect } from '@playwright/test';
import { readFileSync } from 'fs';
import path from 'path';
type ApiFixtures = {
apiRequest: APIRequestContext;
authToken: string;
sampleOrder: Record<string, unknown>;
};
export const test = base.extend<ApiFixtures>({
apiRequest: async ({ playwright }, use) => {
const ctx = await playwright.request.newContext({
baseURL: process.env.API_BASE_URL ?? 'https://api.staging.example.com',
extraHTTPHeaders: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
await use(ctx);
await ctx.dispose();
},
authToken: async ({ apiRequest }, use) => {
const res = await apiRequest.post('/auth/token', {
data: {
email: 'qa@example.com',
password: process.env.QA_PASSWORD,
},
});
expect(res.status()).toBe(200);
const body = await res.json();
await use(body.access_token);
},
sampleOrder: async ({}, use) => {
const raw = readFileSync(
path.join(__dirname, '..', '..', 'fixtures', 'order.json'),
'utf8',
);
await use(JSON.parse(raw));
},
});
export { expect };
Agora importe test desse arquivo em vez de importar diretamente de @playwright/test.
// tests/orders.spec.ts
import { test, expect } from './fixtures/api';
test('POST /orders retorna pedido válido com desconto de 15%', async ({
apiRequest,
authToken,
sampleOrder,
}) => {
const res = await apiRequest.post('/orders', {
headers: {
Authorization: `Bearer ${authToken}`,
},
data: {
...sampleOrder,
coupon: 'SAVE15',
},
});
expect(res.status()).toBe(201);
const body = await res.json();
expect(body).toMatchObject({
id: expect.any(String),
status: 'pending',
discount_pct: 15,
total_cents: expect.any(Number),
});
expect(body.total_cents).toBeLessThan(sampleOrder.subtotal_cents);
});
Esse teste ainda é útil no Playwright porque valida uma regra crítica: o cupom precisa aplicar 15%.
Mas ele não substitui validação completa de schema. É aí que o Apidog entra.
Importando o contrato no Apidog
No Apidog:
- Abra o projeto.
- Clique em Importar.
- Selecione o mesmo
openapi.yamlusado no repositório. - Gere endpoints, parâmetros, exemplos e schemas.
- Crie cenários para jornadas críticas, como:
- cadastro;
- login;
- checkout;
- cancelamento;
- reembolso;
- webhooks.
Dentro do cenário equivalente a POST /orders, use o mesmo payload fixtures/order.json como dado de entrada.
Depois, adicione validações como:
- status esperado:
201; - schema do componente
Order; - campos obrigatórios;
- enums;
- tipos;
- regras de negócio relevantes.
O Playwright valida a regra de alto valor no contexto da aplicação. O Apidog valida o contrato completo da API.
Para mais contexto sobre ferramentas de QA, veja ferramentas de teste de API para engenheiros de QA.
Usando page.route para isolar a UI
Quando você precisa testar a UI sem depender do backend real, use page.route.
test('dashboard renderiza lista de pedidos em modo offline', async ({
page,
sampleOrder,
}) => {
await page.route('**/api/orders', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
orders: [sampleOrder],
}),
});
});
await page.goto('/dashboard');
await expect(page.getByTestId('order-row')).toHaveCount(1);
});
Use esse padrão para:
- evitar instabilidade do staging;
- testar estados específicos da UI;
- simular erros controlados;
- validar loading, empty state e retry.
Mas não trate page.route como substituto de testes de API. Ele isola a UI; não valida o backend real.
Configurando Playwright + Apidog na CI
Um pipeline simples no GitHub Actions pode executar as duas suítes em paralelo.
name: tests
on: [push, pull_request]
jobs:
playwright:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
env:
API_BASE_URL: ${{ secrets.API_BASE_URL }}
QA_PASSWORD: ${{ secrets.QA_PASSWORD }}
apidog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm i -g apidog-cli
- run: apidog-cli run ./apidog/scenarios/checkout.json --reporters cli,junit
env:
API_BASE_URL: ${{ secrets.API_BASE_URL }}
A regra deve ser direta: se Playwright ou Apidog falhar, o merge é bloqueado.
A documentação do GitHub Actions cobre cache, matrix builds e paralelização caso a suíte cresça.
Passo a passo de implementação
1. Padronize o contrato
Coloque openapi.yaml na raiz do repositório.
Trate a especificação como código:
- revisão obrigatória em PR;
- versionamento para breaking changes;
- schemas completos;
- exemplos reais de request e response;
- enums documentados.
Se ainda não existe OpenAPI, gere um rascunho a partir do framework backend e revise manualmente.
2. Centralize fixtures
Evite fixtures duplicados.
Use arquivos como:
fixtures/user.json
fixtures/order.json
fixtures/payment.json
Esses arquivos devem alimentar:
- testes Playwright;
- cenários Apidog;
- mocks;
- exemplos de request.
3. Adicione smoke checks de API no Playwright
Não valide tudo no Playwright. Foque em regras críticas relacionadas ao fluxo de UI.
Exemplos:
expect(res.status()).toBe(201);
expect(body.status).toBe('pending');
expect(body.discount_pct).toBe(15);
Evite testes Playwright enormes que tentam validar todo o contrato.
4. Valide schema no Apidog
No Apidog, use a especificação OpenAPI para validar:
- campos obrigatórios;
- tipos;
- formatos;
- enums;
- responses de erro;
- cenários encadeados.
Exemplo de cenário:
- Criar pedido.
- Buscar pedido.
- Aplicar pagamento.
- Cancelar pedido.
- Verificar status final.
- Validar payload de webhook.
5. Execute tudo na CI
Inclua ambos no pipeline:
{
"scripts": {
"test:e2e": "playwright test",
"test:api": "apidog-cli run ./apidog/scenarios/checkout.json --reporters cli,junit"
}
}
Depois:
npm run test:e2e
npm run test:api
Detectando drift de contrato
A classe de bug mais perigosa é:
200 OK, mas payload errado.
Para reduzir isso:
- compare o
openapi.yamlatual com a versão usada nos testes; - falhe a build se um campo mudar de tipo;
- trate mudança de campo obrigatório como breaking change;
- rode validação de schema em cada cenário Apidog.
Também vale agendar uma execução diária contra staging para capturar mudanças fora do fluxo normal de PR.
Técnicas avançadas
Ative traces no Playwright
No playwright.config.ts:
import { defineConfig } from '@playwright/test';
export default defineConfig({
retries: 2,
use: {
trace: 'on-first-retry',
},
});
Quando um teste falhar na CI, o trace ajuda a inspecionar:
- chamadas de rede;
- snapshots do DOM;
- console logs;
- screenshots;
- ações do usuário.
Combine isso com relatórios do Apidog CLI para entender se a falha começou na UI ou na API.
Use mocks do Apidog para desenvolvimento offline
Quando staging estiver instável, aponte o frontend para um mock gerado a partir da especificação OpenAPI.
Esse padrão ajuda quando:
- o backend está em deploy;
- o banco de staging foi resetado;
- você precisa reproduzir um estado específico;
- o frontend precisa avançar antes do backend estar pronto.
Veja também o conteúdo sobre geração de testes de API assistida por IA.
Limite retries
Use retries para reduzir ruído, não para esconder instabilidade.
export default defineConfig({
retries: 2,
});
Se um teste precisa de muitas tentativas para passar, ele provavelmente tem um problema real:
- dependência externa instável;
- dados compartilhados;
- tempo de espera incorreto;
- backend lento;
- fixture inconsistente.
Marque testes por prioridade
Separe a suíte por frequência de execução:
-
@smoke: todo push; -
@regression: PRs para a branch principal; -
@nightly: suíte completa; -
@contract: validações de contrato; -
@webhook: fluxos assíncronos.
Exemplo:
test('@smoke usuário consegue abrir dashboard', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});
Erros comuns
Evite estes padrões:
- validar apenas
status === 200; - hardcodar bearer tokens;
- manter fixtures separados para Playwright e Apidog;
- não executar o Apidog CLI na CI;
- usar
page.routecomo substituto de teste de API; - validar regras financeiras apenas pela UI;
- ignorar responses de erro;
- deixar drift de schema como warning.
Para APIs com comportamento não determinístico, veja o guia sobre como testar APIs de agentes de IA.
Comparação de ferramentas
| Pilha | Pontos fortes | Pontos fracos | Melhor para |
|---|---|---|---|
Apenas Playwright com request
|
Uma ferramenta, rápido, integrado à suíte | Validação de schema superficial, pouca cobertura de erro, cenários encadeados ficam verbosos | Equipes pequenas e APIs simples |
| Playwright + Postman | Ecossistema maduro, Newman CLI | Coleções podem divergir do OpenAPI, manutenção duplicada | Times já padronizados em Postman |
| Playwright + Apidog | OpenAPI como fonte única, validação de schema, mocks, CLI para CI, fluxo design-first | Duas ferramentas para aprender, exige disciplina no contrato | Equipes que querem cobertura de UI e API orientada por especificação |
| Cypress + cy-api | Familiar para usuários de Cypress | Teste de API mais limitado e dependente de plugins | Bases já existentes em Cypress |
| Pact | Contratos orientados ao consumidor, forte para microsserviços | Curva de aprendizado maior, broker, não cobre UI | Organizações com muitos consumidores internos de API |
Se você vem de ferramentas SOAP ou suítes legadas, estes guias podem ajudar:
- alternativas ao script Groovy do SoapUI;
- alternativas ao ReadyAPI;
- extensões de cliente REST para VSCode;
- alternativas auto-hospedadas ao Postman.
Casos de uso práticos
Checkout de e-commerce
Playwright valida o fluxo visual:
- adicionar item ao carrinho;
- aplicar cupom;
- finalizar compra;
- exibir confirmação.
Apidog valida a cadeia de API:
- criar intenção de pagamento;
- validar antifraude;
- decrementar estoque;
- confirmar pedido;
- validar webhook de pagamento.
Se um gateway muda error_code para errorCode, a validação de schema detecta antes de virar bug de produção.
Dashboard SaaS com gráficos
Playwright valida que o gráfico renderiza.
Apidog valida que os endpoints retornam:
- somas corretas;
- percentis corretos;
- séries agrupadas por tempo;
- valores esperados para filtros;
- payload compatível com o schema.
Um gráfico pode parecer correto mesmo quando a agregação da API está errada.
Fluxo baseado em webhook
Playwright cobre o portal do usuário.
Apidog cobre:
- entrega de webhook;
- assinatura;
- idempotência;
- retry;
- rejeição de duplicidade;
- consistência eventual.
Esse tipo de fluxo é difícil de cobrir apenas com testes de navegador.
Conclusão
Playwright é excelente para fluxos de navegador. Mas testes de navegador não substituem validação profunda de API.
A combinação Playwright + Apidog permite:
- usar OpenAPI como contrato único;
- compartilhar fixtures;
- validar schema e regras de negócio;
- simular APIs quando necessário;
- executar UI e API no mesmo pipeline;
- capturar regressões de contrato antes do deploy.
Comece pequeno:
- escolha uma jornada crítica, como checkout ou cadastro;
- crie o fixture Playwright;
- importe o
openapi.yamlno Apidog; - implemente o cenário equivalente;
- rode ambos na CI.
Depois expanda para fluxos de erro, webhooks, permissões e regressão completa.
FAQ
Posso validar APIs em testes Playwright sem Apidog?
Sim. Use o fixture request do Playwright e expect manual.
Exemplo:
const res = await request.get('/orders');
expect(res.status()).toBe(200);
const body = await res.json();
expect(body.orders).toEqual(expect.any(Array));
Isso cobre checks básicos. Para schema, cenários encadeados, mocks e paths de erro em escala, uma ferramenta dedicada como o Apidog reduz manutenção manual.
Preciso de uma especificação OpenAPI?
Para obter o benefício completo, sim.
Sem OpenAPI, você ainda pode rodar Playwright e Apidog lado a lado, mas perde a fonte única de verdade e tende a duplicar fixtures.
Como lidar com autenticação?
Busque um token novo no início da execução.
No Playwright, exponha o token como fixture. No Apidog, salve o token em variável de ambiente do cenário.
Evite tokens fixos em arquivos versionados.
Cenários Apidog substituem Playwright?
Não.
Apidog valida APIs. Playwright valida navegador, DOM, cliques, layout, acessibilidade visual e comportamento da UI.
As ferramentas cobrem superfícies diferentes.
E se meu staging for instável?
Use mocks baseados no OpenAPI para desenvolvimento e isolamento da UI.
Depois rode os cenários Apidog contra o backend real quando o ambiente estiver saudável.
Como manter a CI rápida?
Use camadas:
- smoke tests em todo push;
- regressão em PRs principais;
- suíte completa em execução noturna;
- paralelização no Playwright;
- execução segmentada dos cenários Apidog.
Como começar hoje?
Baixe o Apidog, importe sua especificação OpenAPI e crie o primeiro cenário para uma jornada crítica da aplicação.
Top comments (0)