Skip to content

Cypress Debugging Techniques

Debugging a failing or confusing test efficiently is its own skill. This lesson covers the core debugging tools Cypress provides and how to combine them with browser DevTools.

Core Debugging Tools

cy.pause() halts test execution at that exact point, letting you inspect the app manually and step through remaining commands one at a time. cy.debug() logs the current subject to the browser console and triggers a debugger breakpoint, useful when working directly in DevTools.

cy.get('[data-cy="cart-total"]').debug(); // logs subject, pauses at a breakpoint
cy.pause(); // halts here; click "Next" in the Test Runner to continue

Both commands are meant for temporary use during development, not for committing into a finished test.

Debugging Command Syntax

cy.pause()
cy.debug()
cy.get(selector).debug()
cy.log('a custom message')
debugger; // plain JS, works inside .then()
  • cy.pause() can be placed anywhere in a chain to halt execution at that point.
  • cy.debug() logs the current subject and triggers a breakpoint if DevTools are open.
  • cy.log() writes a custom message directly into the command log for context.
  • A plain debugger; statement works inside .then() callbacks like normal JavaScript.

Debugging Tools Cheat Sheet

Choosing the right debugging tool for a given situation.

Goal Tool
Pause and manually inspect the app cy.pause()
Log the current subject and set a breakpoint cy.debug()
Add a custom note to the command log cy.log('message')
Step through custom .then() logic debugger; inside the callback
Inspect DOM snapshot at any command Click that command in the Test Runner

Combining cy.pause() with Browser DevTools

With the Test Runner's browser DevTools open (they work exactly like normal Chrome/Firefox DevTools), cy.pause() gives you a frozen moment to inspect the real DOM, check computed styles, or run manual JavaScript in the console, all against the actual state your test reached.

  • Open DevTools before pausing, so you don't miss the frozen state.
  • Use the Elements panel to inspect exact computed styles and attributes.
  • Use the Console panel to run ad hoc JavaScript against the live page.

Debugging Custom Logic Inside .then()

Custom .then() callbacks run as plain JavaScript, so a standard debugger; statement works exactly as it would anywhere else, pausing execution when DevTools are open and letting you step through with normal browser debugging controls.

cy.get('[data-cy="cart-items"]').then(($items) => {
  const total = [...$items].reduce((sum, el) => sum + Number(el.dataset.price), 0);
  debugger; // inspect total and $items here
  expect(total).to.be.greaterThan(0);
});

Common Mistakes

  • Leaving cy.pause() or cy.debug() calls committed in finished test code, unintentionally freezing CI runs.
  • Debugging exclusively by reading terminal output from headless runs instead of using the interactive Test Runner.
  • Not opening DevTools before pausing, missing the chance to inspect the frozen state.
  • Overusing cy.log() everywhere instead of relying on the command log's built-in step-by-step visibility.

Key Takeaways

  • cy.pause() halts execution for manual inspection; cy.debug() logs the subject and sets a breakpoint.
  • Browser DevTools work normally inside the Test Runner and pair well with cy.pause().
  • Plain debugger; statements work inside .then() callbacks like any other JavaScript.
  • Debugging tools are for development use only and should not remain in committed test code.

Pro Tip

Before reaching for cy.pause(), try clicking through the command log in the interactive Test Runner first, the DOM snapshots it already captured often answer the question immediately, without needing to halt and manually re-inspect anything.