Debugging

Debugging is an essential part of writing reliable and accurate tests. Cypress provides powerful tools to help you identify and fix issues in your tests or application. This tutorial will walk you through various techniques and tools for debugging Cypress tests.

Understanding Debugging in Cypress

Debugging in Cypress involves:

  • Identifying why a test fails.
  • Examining the application's state at different points.
  • Reviewing logs and screenshots.

Cypress makes debugging easier with features like time travel, console logs, and built-in commands for inspecting elements.

Using the Cypress Test Runner

The Cypress Test Runner is a visual interface that helps you see your test execution step by step.

How to Use It

  • Run npx cypress open to launch the Test Runner.
  • Select the test file you want to run.
  • Watch the test execute in the browser.

Time Travel

  • Hover over commands in the Command Log (left panel) to see the state of the application at that specific step.
  • The DOM snapshot updates as you move through the commands.

Debugging with .debug()

The .debug() command pauses the test and shows the current state of the element in the browser's developer tools.

Example

Javascript
Copy
cy.get('input#username').debug(); // Pauses and shows the element in dev tools

Pausing Tests with .pause()

Use .pause() to stop the test at a specific point. This allows you to manually inspect the application.

Example

Javascript
Copy
cy.get('button#submit').pause(); // Stops the test here

When the test pauses, you can resume it by clicking the "Resume" button in the Test Runner.

Using Browser Developer Tools

The Cypress Test Runner runs in a browser, so you can use developer tools (DevTools) for advanced debugging.

Steps

  • Right-click in the test browser and select Inspect.
  • Use the Console tab to log messages or inspect variables.
  • Use the Elements tab to inspect the DOM structure.

Example: Log to Console

Javascript
Copy
cy.get('input#username').then(($el) => {
  console.log('Input element:', $el);
});

Using cy.log() for Custom Messages

Add custom messages to the Command Log using cy.log().

Example

Javascript
Copy
cy.log('Navigating to the homepage');
cy.visit('/home');
cy.log('Filling out the login form');

Checking Errors in the Command Log

When a test fails, the Command Log in the Test Runner highlights the failed command. Click on the failed step to see:

  • The error message.
  • A DOM snapshot.
  • Relevant details like element visibility, state, or assertions.

Using Screenshots and Videos

Cypress automatically captures screenshots and videos during test runs to help identify issues.

Screenshots

  • Taken automatically on test failure.
  • Can also be captured manually:
Javascript
Copy
cy.screenshot('custom-name'); // Takes a screenshot with the name "custom-name"

Videos

Recorded automatically when running tests with cypress run.

Debugging Network Requests

Use cy.intercept() to monitor and debug API calls.

Example: Debugging API Responses

Javascript
Copy
cy.intercept('GET', '/api/users').as('getUsers');
cy.visit('/users');
cy.wait('@getUsers').then((interception) => {
  console.log('API response:', interception.response.body);
});

Debugging Assertions

When an assertion fails, Cypress provides detailed error messages, including:

  • What was expected.
  • What was received.
  • Suggestions for resolving the issue.

Example

Javascript
Copy
cy.get('button#submit').should('be.visible'); // If this fails, you'll see why

Enable Debug Logging

Cypress logs useful debugging information. To see these logs:

  1. Open the browser's developer tools.
  2. Go to the Console tab.
  3. Enable verbose logging by setting the DEBUG environment variable:
DEBUG=cypress:* npx cypress open

Common Debugging Scenarios

Element Not Found

  • Check if the element exists in the DOM using cy.get().
  • Verify the correct CSS selector.
  • Add a .should('be.visible') assertion to ensure it's visible.

Timing Issues

  • Add a cy.wait() to handle delays or slow responses.
  • Use assertions to confirm the element's state.

Flaky Tests

Retry failed commands by enabling test retries in cypress.json:

JSON
Copy
{
  "retries": {
    "runMode": 2,
    "openMode": 1
  }
}

Use Plugins for Advanced Debugging

Cypress plugins can enhance debugging capabilities:

  • Cypress Testing Library: Simplifies element selection.
  • cypress-axe: Helps debug accessibility issues.

Install a plugin:

npm install --save-dev @testing-library/cypress

Debugging with cy.task()

The cy.task() command allows you to run custom Node.js code for debugging backend processes or logging.

Example

In plugins/index.js:

Javascript
Copy
module.exports = (on) => {
  on('task', {
    logMessage(message) {
      console.log(message);
      return null;
    }
  });
};

In your test:

Javascript
Copy
cy.task('logMessage', 'This is a custom log');

Best Practices for Debugging

  • Start Small: Debug individual commands or assertions before reviewing the entire test.
  • Use Cypress Commands: Use .debug() and .log() frequently.
  • Check the Command Log: Review the Command Log for failed steps and snapshots.
  • Reproduce the Issue: Isolate the failing test to consistently reproduce the problem.
  • Use the Test Runner: Time travel and DOM snapshots are invaluable tools.