Pular para o conteúdo principal

Guia de teste do Playwright: testes E2E para aplicativos Next.js

Escreva testes ponta a ponta confiáveis ​​para aplicativos Next.js com Playwright. Guia completo que abrange configuração, objetos de página, testes de autenticação, regressão visual e integração de CI/CD.

E
ECOSIRE Research and Development Team
|5 de março de 20267 min de leitura1.2k Palavras|

Os testes de ponta a ponta detectam os bugs que os testes de unidade não detectam: fluxos de autenticação quebrados, falhas no envio de formulários, erros de navegação e problemas de renderização entre navegadores.

Os testes de ponta a ponta detectam os bugs que os testes de unidade não detectam: fluxos de autenticação quebrados, falhas no envio de formulários, erros de navegação e problemas de renderização entre navegadores. O Playwright, criado pela Microsoft, tornou-se a principal estrutura de testes E2E com seu suporte a vários navegadores, recursos de espera automática e poderosas ferramentas de depuração.

Principais conclusões

  • Os testes do Playwright são executados no Chromium, Firefox e WebKit a partir de um único conjunto de testes
  • A espera automática elimina testes instáveis, aguardando que os elementos sejam acionáveis antes de interagir
  • O estado de autenticação pode ser compartilhado entre testes para uma execução mais rápida
  • A integração de CI com GitHub Actions fornece testes automatizados em cada solicitação pull

Configuração do projeto

Instalação

npm init playwright@latest

Isso instala o Playwright, cria um arquivo de configuração e baixa os binários do navegador. Para projetos Next.js, configure o servidor web para iniciar automaticamente:

// playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
  testDir: "./e2e",
  timeout: 30000,
  retries: process.env.CI ? 2 : 0,
  use: {
    baseURL: "http://localhost:3000",
    screenshot: "only-on-failure",
    trace: "on-first-retry",
  },
  webServer: {
    command: "npm run dev",
    port: 3000,
    reuseExistingServer: !process.env.CI,
  },
  projects: [
    { name: "chromium", use: { browserName: "chromium" } },
    { name: "firefox", use: { browserName: "firefox" } },
    { name: "webkit", use: { browserName: "webkit" } },
  ],
});

Escrevendo seu primeiro teste

Teste Básico de Navegação

// e2e/navigation.spec.ts
import { test, expect } from "@playwright/test";

test("home page loads and displays title", async ({ page }) => {
  await page.goto("/");
  await expect(page).toHaveTitle(/ECOSIRE/);
  await expect(page.getByRole("heading", { level: 1 })).toBeVisible();
});

test("navigation to services page", async ({ page }) => {
  await page.goto("/");
  await page.getByRole("link", { name: "Services" }).click();
  await expect(page).toHaveURL(/services/);
  await expect(page.getByRole("heading", { name: /Services/ })).toBeVisible();
});

Teste de envio de formulário

test("contact form submission", async ({ page }) => {
  await page.goto("/contact");

  await page.getByLabel("Name").fill("Test User");
  await page.getByLabel("Email").fill("test@example.com");
  await page.getByLabel("Message").fill("This is a test message");
  await page.getByRole("button", { name: "Send" }).click();

  await expect(page.getByText("Message sent")).toBeVisible();
});

Padrão de objeto de página

Encapsule interações de página em objetos de página para manutenção:

// e2e/pages/login.page.ts
import { Page, expect } from "@playwright/test";

export class LoginPage {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto("/login");
  }

  async login(email: string, password: string) {
    await this.page.getByLabel("Email").fill(email);
    await this.page.getByLabel("Password").fill(password);
    await this.page.getByRole("button", { name: "Sign In" }).click();
  }

  async expectLoggedIn() {
    await expect(this.page).toHaveURL(/dashboard/);
  }

  async expectError(message: string) {
    await expect(this.page.getByText(message)).toBeVisible();
  }
}

Use em testes:

test("successful login", async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login("user@example.com", "password123");
  await loginPage.expectLoggedIn();
});

Teste de autenticação

Estado de autenticação compartilhada

Evite fazer login antes de cada teste salvando o estado de autenticação:

// e2e/auth.setup.ts
import { test as setup } from "@playwright/test";

setup("authenticate", async ({ page }) => {
  await page.goto("/login");
  await page.getByLabel("Email").fill("admin@example.com");
  await page.getByLabel("Password").fill("admin-password");
  await page.getByRole("button", { name: "Sign In" }).click();
  await page.waitForURL("/dashboard");

  // Save authentication state
  await page.context().storageState({ path: ".auth/user.json" });
});

Configure em playwright.config.ts:

projects: [
  { name: "setup", testMatch: /auth\.setup\.ts/ },
  {
    name: "authenticated",
    dependencies: ["setup"],
    use: { storageState: ".auth/user.json" },
  },
],

Teste de regressão visual

Capture alterações visuais não intencionais com comparações de capturas de tela:

test("home page visual regression", async ({ page }) => {
  await page.goto("/");
  await expect(page).toHaveScreenshot("home-page.png", {
    maxDiffPixelRatio: 0.01,
  });
});

Na primeira execução, o Playwright salva capturas de tela básicas. As execuções subsequentes são comparadas com as linhas de base e falham se as diferenças excederem o limite. Atualize as linhas de base com --update-snapshots quando as alterações forem intencionais.


Simulação de API

Respostas simuladas da API para testes determinísticos:

test("displays products from API", async ({ page }) => {
  await page.route("/api/products", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([
        { id: 1, name: "Product A", price: 29.99 },
        { id: 2, name: "Product B", price: 49.99 },
      ]),
    });
  });

  await page.goto("/products");
  await expect(page.getByText("Product A")).toBeVisible();
  await expect(page.getByText("Product B")).toBeVisible();
});

Integração CI/CD

Ações do GitHub

name: E2E Tests
on: [push, pull_request]
jobs:
  test:
    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
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/

Os relatórios de teste com falha são carregados como artefatos para depuração, incluindo capturas de tela, rastreamentos e gravações de vídeo.


Ferramentas de depuração

  • Playwright Inspector: Execute testes com sinalizador --debug para execução passo a passo
  • Trace Viewer: abra rastreamentos para ver cada ação, solicitação de rede e instantâneo do DOM
  • Codegen: execute npx playwright codegen para registrar interações do navegador e gerar código de teste
  • Extensão do VS Code: execute e depure testes diretamente do VS Code com elementos clique para localizar

Melhores práticas

  1. Use seletores baseados em função: prefira getByRole, getByLabel, getByText em vez de seletores CSS
  2. Evite esperas codificadas: confie na espera automática em vez de page.waitForTimeout()
  3. Testes isolados: cada teste deve ser independente e não depender de outros testes
  4. Teste fluxos de usuários, não implementação: concentre-se no que os usuários fazem, não em como o código funciona
  5. Mantenha os testes rápidos: use atalhos de API para configuração (crie dados de teste via API, não UI)
  6. Executar em CI: cada solicitação pull deve passar nos testes E2E antes da mesclagem

Perguntas frequentes

P: Como o Playwright se compara ao Cypress?

O Playwright oferece suporte nativo a vários navegadores (Chromium, Firefox, WebKit), enquanto o Cypress visa principalmente o Chromium. O Playwright é mais rápido para execução paralela e lida com várias guias/janelas. Cypress tem uma curva de aprendizado um pouco mais fácil e uma depuração de viagem no tempo mais forte.

P: Como lidamos com testes instáveis?

A espera automática do dramaturgo elimina a maior parte da instabilidade. Para os problemas restantes: use asserções web-first (espera o localizador), evite testar o comportamento dependente de tempo e configure novas tentativas no CI. Os relatórios de rastreamento ajudam a identificar a causa raiz das falhas intermitentes.

P: Devemos testar todas as páginas?

Concentre-se em fluxos críticos de usuários: autenticação, fluxos de trabalho principais de negócios, envios de formulários e fluxos de pagamento. Nem todas as páginas precisam de testes E2E – use testes de unidade e integração para cobertura em nível de componente.

P: Quanto tempo devem durar os testes E2E?

Os testes individuais devem ser concluídos em menos de 30 segundos. Um conjunto completo para um aplicativo de médio porte (50 a 100 testes) deve ser executado em menos de 10 minutos com execução paralela.


O que vem a seguir

O teste E2E com Playwright oferece confiança de que seu aplicativo funciona corretamente do ponto de vista do usuário. Comece com fluxos críticos e expanda a cobertura à medida que sua aplicação cresce.

Entre em contato com a ECOSIRE para obter ajuda na automação de testes ou explore nossos serviços de implementação Odoo para implantação de ERP com qualidade garantida.


Publicado pela ECOSIRE – ajudando empresas a escalar com soluções de software empresarial.

E

Escrito por

ECOSIRE Team

Technical Writing

The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.

ECOSIRE

Expanda o seu negócio com ECOSIRE

Soluções empresariais em ERP, comércio eletrônico, IA, análise e automação.