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
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
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
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
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:
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
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
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:
- Open the browser's developer tools.
- Go to the Console tab.
- 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:
{ "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:
module.exports = (on) => { on('task', { logMessage(message) { console.log(message); return null; } }); };
In your test:
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.