Guía de pruebas de dramaturgos: pruebas E2E para aplicaciones Next.js

Escriba pruebas confiables de un extremo a otro para aplicaciones Next.js con Playwright. Guía completa que cubre configuración, objetos de página, pruebas de autenticación, regresión visual e integración de CI/CD.

E

ECOSIRE Research and Development Team

Equipo ECOSIRE

5 de marzo de 20266 min de lectura1.3k Palabras

Guía de pruebas de dramaturgos: pruebas E2E para aplicaciones Next.js

Las pruebas de un extremo a otro detectan los errores que las pruebas unitarias pasan por alto: flujos de autenticación rotos, fallas en el envío de formularios, errores de navegación y problemas de representación entre navegadores. Playwright, creado por Microsoft, se ha convertido en el marco de pruebas E2E líder con su soporte para múltiples navegadores, capacidades de espera automática y potentes herramientas de depuración.

Conclusiones clave

  • Las pruebas de Playwright se ejecutan en Chromium, Firefox y WebKit desde un único conjunto de pruebas
  • La espera automática elimina las pruebas inestables al esperar a que los elementos sean procesables antes de interactuar
  • El estado de autenticación se puede compartir entre pruebas para una ejecución más rápida
  • La integración de CI con GitHub Actions proporciona pruebas automatizadas en cada solicitud de extracción

Configuración del proyecto

Instalación

npm init playwright@latest

Esto instala Playwright, crea un archivo de configuración y descarga los archivos binarios del navegador. Para proyectos Next.js, configure el servidor web para que se inicie automáticamente:

// 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" } },
  ],
});

Escribir tu primera prueba

Prueba de navegación básica

// 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();
});

Prueba de envío de formulario

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

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

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

Patrón de objeto de página

Encapsule las interacciones de la página en objetos de la página para facilitar el mantenimiento:

// 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();
  }
}

Uso en pruebas:

test("successful login", async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login("[email protected]", "password123");
  await loginPage.expectLoggedIn();
});

Prueba de autenticación

Estado de autenticación compartida

Evite iniciar sesión antes de cada prueba guardando el estado de autenticación:

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

setup("authenticate", async ({ page }) => {
  await page.goto("/login");
  await page.getByLabel("Email").fill("[email protected]");
  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 en playwright.config.ts:

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

Prueba de regresión visual

Capte cambios visuales no deseados con comparaciones de capturas de pantalla:

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

En la primera ejecución, Playwright guarda capturas de pantalla de referencia. Las ejecuciones posteriores se comparan con las líneas de base y fallan si las diferencias exceden el umbral. Actualice las líneas base con --update-snapshots cuando los cambios sean intencionales.


Burla de API

Respuestas simuladas de API para pruebas deterministas:

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();
});

Integración CI/CD

Acciones de 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/

Los informes de pruebas fallidas se cargan como artefactos para la depuración, incluidas capturas de pantalla, seguimientos y grabaciones de vídeo.


Herramientas de depuración

  • Inspector de dramaturgos: ejecute pruebas con el indicador --debug para una ejecución paso a paso
  • Visor de seguimiento: abra seguimientos para ver cada acción, solicitud de red e instantánea de DOM
  • Codegen: ejecuta npx playwright codegen para registrar las interacciones del navegador y generar código de prueba.
  • Extensión de VS Code: ejecute y depure pruebas directamente desde VS Code con elementos de hacer clic para localizar

Mejores prácticas

  1. Utilice selectores basados en roles: prefiera getByRole, getByLabel, getByText a los selectores CSS
  2. Evite esperas codificadas: confíe en la espera automática en lugar de en page.waitForTimeout()
  3. Pruebas aisladas: cada prueba debe ser independiente y no depender de otras pruebas.
  4. Prueba los flujos de usuarios, no la implementación: céntrate en lo que hacen los usuarios, no en cómo funciona el código.
  5. Mantenga las pruebas rápidas: use accesos directos de API para la configuración (cree datos de prueba a través de API, no de UI)
  6. Ejecutar en CI: cada solicitud de extracción debe pasar las pruebas E2E antes de fusionarse

Preguntas frecuentes

P: ¿Cómo se compara Playwright con Cypress?

Playwright supports multiple browsers (Chromium, Firefox, WebKit) natively, while Cypress primarily targets Chromium. Playwright es más rápido para la ejecución paralela y maneja múltiples pestañas/ventanas. Cypress tiene una curva de aprendizaje ligeramente más sencilla y una depuración de viajes en el tiempo más sólida.

P: ¿Cómo manejamos las pruebas inestables?

La espera automática del dramaturgo elimina la mayor parte de la debilidad. Para los problemas restantes: utilice aserciones web primero (localizador de espera), evite probar el comportamiento dependiente del tiempo y configure los reintentos en CI. Los informes de seguimiento ayudan a identificar la causa raíz de los fallos intermitentes.

P: ¿Deberíamos probar cada página?

Céntrese en los flujos de usuarios críticos: autenticación, flujos de trabajo comerciales principales, envío de formularios y flujos de pago. No todas las páginas necesitan pruebas E2E: utilice pruebas unitarias y de integración para la cobertura a nivel de componentes.

P: ¿Cuánto tiempo deben durar las pruebas E2E?

Las pruebas individuales deberían completarse en menos de 30 segundos. Un conjunto completo para una aplicación de tamaño mediano (50-100 pruebas) debería ejecutarse en menos de 10 minutos con ejecución paralela.


¿Qué sigue?

Las pruebas E2E con Playwright brindan la confianza de que su aplicación funciona correctamente desde la perspectiva del usuario. Comience con flujos críticos y amplíe la cobertura a medida que crezca su aplicación.

Comuníquese con ECOSIRE para obtener ayuda sobre la automatización de pruebas, o explore nuestros servicios de implementación de Odoo para una implementación de ERP con garantía de calidad.


Publicado por ECOSIRE: ayuda a las empresas a escalar con soluciones de software empresarial.

E

Escrito por

ECOSIRE Research and Development Team

Construyendo productos digitales de nivel empresarial en ECOSIRE. Compartiendo perspectivas sobre integraciones Odoo, automatización de eCommerce y soluciones empresariales impulsadas por IA.

Chatea en whatsapp