End-to-End Testing

Cypress

Cypress ejecuta pruebas dentro del navegador con un runner interactivo, reintentos automáticos y un depurador de viaje en el tiempo que hace que las pruebas end-to-end sean excepcionalmente accesibles.

intermediate13 min readUpdated 15 sept 2026
login.cy.js
js
// cypress/e2e/login.cy.js
describe("login", () => {
  it("signs the user in", () => {
    cy.visit("/login");

    cy.get('[data-cy="email"]').type("[email protected]");
    cy.get('[data-cy="password"]').type("secret");
    cy.get('[data-cy="submit"]').click();

    cy.contains("h1", "Dashboard").should("be.visible");
  });
});
Se ejecuta en
El navegador
Reintentos
Automáticos
Depuración
Runner de viaje en el tiempo
Red
cy.intercept
Lenguaje
JavaScript o TypeScript
Navegadores
Chrome, Firefox, Edge, WebKit

Por que importa

Por qué a los desarrolladores les gusta Cypress

Runner interactivo

Observa la ejecución de los comandos sobre la aplicación en vivo, inspecciona el DOM en cada paso y viaja en el tiempo a cualquier punto de la prueba.

Reintentos automáticos

Los comandos y las aserciones se reintentan hasta que pasan o expiran, lo que elimina la mayoría de las esperas manuales.

Stubbing de red

Intercepta y simula peticiones con cy.intercept para probar estados de error y casos borde de forma determinista.

La imagen completa

Las tres ideas detrás de Cypress

Las pruebas se ejecutan dentro del navegador, los comandos se encolan automáticamente y las aserciones se reintentan hasta que pasan.

Comandos

Actuar

Una API encadenable para visitar páginas, consultar elementos e interactuar con ellos.

Aserciones

Verificar

Aserciones should y expect que se reintentan contra el DOM en vivo.

El runner

Ejecutar

Un proceso de Node.js controla el navegador y sirve el runner de pruebas interactivo.

Cypress de un vistazo

El núcleo de Cypress

cy.visit

Abre una página e inicia una prueba.

cy.get y cy.contains

Consulta elementos mediante selectores, texto o helpers al estilo de testing-library.

should

Aserciones que se reintentan hasta que la condición sea verdadera.

Interacciones

type, click, select, trigger y más, todos encolados y reintentados.

cy.intercept

Simula, espía y modifica peticiones y respuestas de red.

Comandos personalizados

Encapsula flujos repetitivos en comandos reutilizables.

Una breve historia

De una herramienta de desarrollo a una plataforma de pruebas

  1. 2015

    Lanzamiento de Cypress

    Se introduce una herramienta de pruebas basada en el navegador con un runner interactivo.

    15
  2. 2018

    Cypress 3 y código abierto

    Sigue una adopción más amplia y un ecosistema de plugins creciente tras su lanzamiento como open source.

    18
  3. 2020

    cy.intercept

    Una nueva API de red reemplaza a cy.route y mejora el stubbing y el espionaje.

    20
  4. 2022

    Cypress 10 y 12

    Se lanza un nuevo formato de configuración y mejoras en las pruebas de componentes.

    22
  5. Hoy

    Una opción popular de e2e

    Apreciado por su experiencia de desarrollador, con pruebas de componentes y reportes en la nube.

    Hoy

La guia completa

Cypress: Todo lo que necesitas saber

¿Qué es Cypress?

Cypress es una herramienta de pruebas end-to-end que se ejecuta dentro del navegador junto a tu aplicación. Esta decisión arquitectónica le otorga una experiencia de desarrollador excepcionalmente buena: un runner interactivo donde puedes ver la ejecución de los comandos, la capacidad de inspeccionar el DOM en cada paso y un depurador de “viaje en el tiempo” que reproduce cada acción.

Es una de las herramientas de pruebas de navegador más populares y es especialmente apreciada por su facilidad de uso. Los comandos se encolan automáticamente, las aserciones se reintentan hasta que pasan y el runner deja muy claro qué sucedió cuando una prueba falla.

Escribiendo una prueba

Las pruebas de Cypress utilizan una API de comandos encadenables y una estructura describe/it.

// cypress/e2e/todos.cy.js
describe("todos", () => {
  beforeEach(() => {
    cy.visit("/todos");
  });

  it("adds a todo", () => {
    cy.get('[data-cy="new-todo"]').type("Write tests");
    cy.get('[data-cy="add"]').click();

    cy.get('[data-cy="todo"]').should("have.length", 1);
    cy.contains("Write tests").should("be.visible");
  });
});

Los comandos de Cypress se encolan y se ejecutan en orden, aunque retornen inmediatamente. Es por eso que debes encadenar .then o usar alias en lugar de asignar el resultado de un comando a una variable.

Comandos y aserciones

Los comandos principales cubren la navegación, las consultas y la interacción:

  • cy.visit(url) abre una página.
  • cy.get(selector) realiza consultas mediante selectores CSS.
  • cy.contains(text) busca un elemento por su texto.
  • .type(), .click(), .select(), .check() interactúan con los elementos.
  • .should() realiza aserciones y reintentos.
// assertions.cy.js
cy.get("form").should("be.visible");
cy.get('[data-cy="count"]').should("have.text", "3");
cy.get("button").should("be.disabled");
cy.get('[data-cy="row"]').should("have.length", 5);

Debido a que .should() reintenta la operación hasta que se cumpla o se agote el tiempo de espera, rara vez es necesario esperar explícitamente. Este es el mismo enfoque basado en reintentos que hace que las pruebas de Playwright sean resilientes, aplicado a una API encadenada.

Stubbing de red con cy.intercept

cy.intercept es la forma de hacer que las pruebas sean deterministas. Permite hacer stub de respuestas, espiar el tráfico real, modificar peticiones y controlar los tiempos de respuesta.

// intercept.cy.js
cy.intercept("GET", "/api/users", {
  statusCode: 500,
  body: { message: "Server error" },
}).as("users");

cy.visit("/users");
cy.wait("@users");

cy.contains("Something went wrong").should("be.visible");

El uso de un alias con cy.wait("@users") te permite realizar aserciones sobre la petición y esperar la respuesta sin tener que adivinar los tiempos de ejecución. Hacer stub de estados de error de esta manera es mucho más fiable que intentar provocarlos desde un backend real.

Comandos personalizados y fixtures

Los flujos que se repiten deben ir en un comando personalizado, lo que permite que los tests sean más legibles.

// cypress/support/commands.js
Cypress.Commands.add("login", (email, password) => {
  cy.visit("/login");
  cy.get('[data-cy="email"]').type(email);
  cy.get('[data-cy="password"]').type(password);
  cy.get('[data-cy="submit"]').click();
});
// usage
cy.login("[email protected]", "secret");

Los fixtures cargan datos estáticos desde cypress/fixtures, y cy.fixture("users.json").then(...) proporciona entradas predecibles para los tests. Combinados con cy.intercept, los fixtures son la forma estándar de testear sin un backend activo.

Selección de elementos

Cypress funciona con selectores CSS, por lo que la tentación de vincular las pruebas al estilo es real. Evítalo. Prioriza, en este orden:

  1. Consultas accesibles a través de @testing-library/cypress (findByRole, findByLabelText).
  2. cy.contains para texto visible.
  3. Un atributo data-cy dedicado cuando no haya una identidad visible para el usuario.

Un atributo data-cy es explícito y estable, por lo que las pruebas sobreviven a los rediseños. Los selectores basados en clases no lo hacen.

Dónde encaja Cypress

Cypress es la capa de end-to-end. Mantén la pirámide equilibrada: tests unitarios rápidos con Vitest o Jest, tests de componentes con Testing Library, y un conjunto enfocado de flujos end-to-end en Cypress o Playwright. Desplaza los casos borde hacia las capas más económicas y reserva el e2e para los caminos que deben funcionar de principio a fin.

Mejores prácticas

  • Simula la red con cy.intercept para obtener pruebas deterministas.
  • Utiliza data-cy o consultas accesibles en lugar de selectores de estilo.
  • Mantén las pruebas independientes para que puedan ejecutarse en paralelo.
  • Encapsula los flujos repetitivos en comandos personalizados.
  • Inicia sesión a través de un comando personalizado o una llamada a la API en lugar de usar la interfaz de usuario en cada ocasión.
  • Realiza aserciones sobre los resultados visibles para el usuario, no sobre el estado interno.
  • Ejecuta en modo headless en CI y reserva el ejecutor interactivo para la depuración local.

Errores comunes

  • Esperar con cy.wait(milliseconds) en lugar de usar un alias de red o una aserción.
  • Acoplar los selectores a clases de CSS y a la estructura.
  • Compartir el estado entre tests, lo que provoca fallos dependientes del orden de ejecución.
  • Intentar almacenar los resultados de los comandos en variables sin usar .then o aliases.
  • Probar todo de extremo a extremo (end-to-end) en lugar de hacerlo en la capa adecuada.
  • Iniciar sesión a través de la UI antes de cada test, ralentizando la suite de pruebas.

Próximos pasos

Cypress es una herramienta amigable y potente para probar flujos reales de usuario. Compárala con Playwright si buscas una alternativa multiplataforma, y construye las capas inferiores con Vitest y Testing Library. Después, añade un comando de login personalizado y un flujo crítico, y haz crecer tu suite de pruebas a partir de ahí.

Manejo de la red

Simula la petición para que la prueba sea determinista y rápida. Esperar a un backend real hace que las pruebas sean lentas e inestables.

Preferir
cy.intercept("GET", "/api/users", {
  statusCode: 500,
  body: { message: "Server error" },
}).as("users");

cy.visit("/users");
cy.wait("@users");
cy.contains("Something went wrong");
Evitar
cy.visit("/users");
cy.wait(3000);
cy.contains("Something went wrong");

Selección de elementos

Un atributo de prueba dedicado es estable frente a cambios de estilo y estructura.

Preferir
cy.get('[data-cy="submit"]').click();
Evitar
cy.get(".btn.btn-primary > span")
  .click();

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Cypress?

Nuestro tutorial interactivo te guia a traves de Cypress paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.