Modern web apps are dynamic, fast, and user-focused. Testing them needs to be just as agile. Cypress is built to meet this need with a testing experience that mirrors real user interactions in the browser.
Overview
What is Cypress?
Cypress is a fast, reliable end-to-end testing framework that runs directly in the browser.
Why is Cypress important?
It offers real-time reloading, flake-free test execution, and powerful debugging. all tailored for modern JavaScript frameworks. Its developer-friendly architecture simplifies test creation and boosts productivity.
How to Run Cypress Tests
- Install Cypress using npm install cypress.
- Launch Cypress with npx cypress open.
- Create your test cases in the cypress/e2e folder.
- Run tests in the Cypress Test Runner UI or headless mode.
- View results and debug with screenshots, logs, and video playback.
This article covers how Cypress works, its core benefits, and a practical guide to start testing modern web applications effectively.
What is Cypress Framework?
Cypress is a JavaScript front-end testing framework meant to make web automation testing easy. Developers and QA engineers can write automated tests that interact directly with the application code and browser in real time.
This approach makes Cypress faster and more stable than conventional Selenium based tools.
Cypress is unique because it runs inside the browser, not outside like most automation tools. This gives it direct access to the DOM, network requests, local storage, and browser APIs, just like a real user, without relying on external protocols.
Also Read: Getting Started with Website Test Automation
Features of the Cypress Framework
Cypress has a robust feature set designed to enhance test stability, performance, and developer experience.
Some of its best features are:
- Same Run-Loop Execution: Tests run inside the browser alongside your app, giving direct access to the DOM, cookies, storage, and network without proxies.
- Automatic Waiting: No need for manual waits, Cypress handles DOM changes and assertions automatically, reducing flakiness.
- Real-Time Reloading: Save a test file, and Cypress reloads instantly, speeding up development.
- Time Travel: View UI snapshots at each test step for easy debugging.
- Clear Error Messages: Failures show readable errors and stack traces with full context.
- Built-In Debugging: Use .debug() or .pause() to inspect app state with DevTools.
- Network Control: Modify or block API calls using cy.intercept() to test various scenarios.
- Test Isolation: Each test runs independently with clean state, ensuring consistent results.
- Cross-Browser Support: Works with Chrome, Firefox, Edge, and Electron.
- Visual Test Runner: The UI shows exactly what each test does, step by step.
Also Read: Top 9 JavaScript Testing Frameworks
Why Cypress For Automation Testing
Old-school automation tools such as Selenium have been working their magic for years. However, new web apps come with different testing requirements.
Cypress addresses several of the issues that developers and QA teams deal with nowadays.
- Fast & Developer-Friendly: Runs directly in the browser for near-instant feedback and no network delays.
- Flake-Free Testing: Auto-waiting, retries, and test isolation ensure stable, CI-friendly test runs.
- Effortless Debugging: Get time travel, screenshots, dev tools access, and detailed logs, all in one view.
- Front-End Ready: Optimized for React, Angular, Vue, Svelte, and supports component-level testing.
- Unified Testing Tool: One framework for end-to-end, API, integration, and (experimental) unit tests.
- Network Control: Easily intercept and stub HTTP requests to test real-world scenarios and edge cases.
- Live Reload: Instant feedback with auto-reloading tests on code changes, which is perfect for TDD.
- Thriving Ecosystem: Backed by a strong community and plugins for CI, reporting, and coverage.
Components of the Cypress Framework
Cypress is more than just a test runner. It has a modular architecture that includes multiple components working together to create, run, and debug test cases efficiently.
- Test Runner (Cypress App): A graphical UI that displays executed commands, screenshots, console logs, and network activity, enabling real-time test debugging with pause and DOM inspection capabilities.
- Cypress CLI: A command-line tool to open the Test Runner, run tests in headless mode, and configure runs for CI/CD pipelines.
- Cypress Configuration (cypress.config.js): Controls test behavior by setting base URLs, file locations, timeouts, environment variables, viewport sizes, and reporting options.
- Test Scripts: Use Mocha and Chai syntax to write tests with .cy.js or .spec.js file extensions.
- Fixtures: Static test data files stored in the cypress/fixtures folder, used to mock APIs or provide input data in formats like JSON or images.
- Support Folder: Contains shared utilities like commands.js where reusable custom commands are defined to keep scripts clean and maintainable.
- Plugins: Extend Cypress with custom tasks like file downloads and reporting via cypress/plugins/index.js, using plugins like cypress-axe or image-snapshot.
Cypress Web Testing Framework Workflow
Cypress follows a streamlined and intuitive workflow that enables testers and developers to write, run, and maintain robust end-to-end tests.
Here’s a practical breakdown of how Cypress works from setup to execution.
Step 1: Install Cypress in your JavaScript project using npm install cypress, ensuring seamless integration with modern frameworks.
Step 2: Launch the Cypress graphical interface using npx cypress open to select browsers, run test files, and view real-time test execution.
Step 3: Write tests using Mocha-style syntax with Chai assertions inside the cypress/e2e/ directory.
Step 4: Run tests in headed mode via the Test Runner or headless mode using npx cypress run for CLI execution.
Step 5: Store static data in cypress/fixtures and define reusable logic in cypress/support to streamline test development.
Example fixture (user.json):
{ "email": "test@example.com", "password": "pass1234" }
Example custom command (cypress/support/commands.js):
Cypress.Commands.add('login', (email, password) => { cy.get('#email').type(email) cy.get('#password').type(password) cy.get('button[type=submit]').click() })
Step 6: Access videos (if enabled), failure screenshots, detailed command logs, and time-travel snapshots for efficient debugging.
Step 7: Seamlessly connect Cypress with Jenkins, GitHub Actions, GitLab, CircleCI, and other CI/CD tools for fast, stable test automation.
Also Read: Cypress Best Practices for Test Automation
Getting Started with Cypress Testing (With Example)
Cypress simplifies end-to-end testing with intuitive commands and built-in assertions.
This section covers essential methods you’ll use daily, with practical examples and syntax explanations.
1. Visiting a Page
cy.visit('https://example.com')
- Loads the given URL in the test browser.
- Starts the test from the defined page.
2. Selecting Elements
By ID:
cy.get('#login-button')
By Class:
cy.get('.menu-item')
By Attribute:
cy.get('[data-testid="submit-btn"]')
Read More: findElement and findElements in Selenium
3. Typing into Fields
cy.get('input[name="email"]').type('user@example.com')
- .type() simulates typing.
- Works on inputs, textareas, or contenteditable elements.
4. Clicking Elements
cy.get('button[type="submit"]').click()
- Triggers a click event.
- Can include { force: true } to override visibility checks.
Must Read: How to handle Click Events in Cypress
5. Assertions with .should()
Cypress uses Chai for assertions.
cy.get('h1').should('contain.text', 'Welcome') cy.url().should('include', '/dashboard') cy.get('input').should('have.value', 'admin')
6. Chaining Commands
Cypress uses a chainable API. Every command waits for the previous one to complete.
cy.get('form') .find('input[name="email"]') .type('test@example.com') .should('have.value', 'test@example.com')
7. Waiting (Implicit & Explicit)
Cypress automatically waits for DOM elements. But you can also wait manually:
cy.wait(1000) // waits 1 second
For dynamic content:
cy.get('.loader', { timeout: 10000 }).should('not.exist')
8. Custom Commands (Reusable)
Inside cypress/support/commands.js, define:
Cypress.Commands.add('login', (email, password) => { cy.get('#email').type(email) cy.get('#password').type(password) cy.get('#login').click() })
Use in your test:
cy.login('user@example.com', '123456')
9. Test Hooks (Before/After)
Set up or tear down preconditions:
before(() => { cy.visit('/login') }) after(() => { cy.clearCookies() })
Use beforeEach to run before every test:
beforeEach(() => { cy.visit('/') })
10. Grouping Tests
describe('Login Tests', () => { it('logs in successfully', () => { // test }) it('shows error on invalid login', () => { // test }) })
Organise related tests under a single suite.
Installing the Cypress Web Testing Framework
Installing Cypress is simple, but setting it up correctly ensures stability and easy maintenance.
Below is a step-by-step guide for installing Cypress in a real-world project.
1. Prerequisites: Before installation, make sure the following are installed:
- Node.js (v12 or higher recommended)
- npm or yarn
- A project folder (already initialized with npm init -y)
Verify:
node -v npm -v
2. Install Cypress via npm: Navigate to your project root folder and run:
npm install Cypress --save-dev
This command adds Cypress as a dev dependency, installs it in node_modules, and enables CLI commands.
If using Yarn:
yarn add Cypress --dev
3. Open Cypress for the First Time to initialize the Cypress folder structure.
npx Cypress open
This creates a cypress folder with the following structure:
cypress/ ├── e2e/ ├── fixtures/ ├── support/ cypress.config.js
The first run also generates sample test files under cypress/e2e to help you get started.
4. Folder Structure Breakdown
Folder/File | Purpose |
---|---|
e2e/ | Store your test spec files |
fixtures/ | JSON or other static test data |
support/ | Custom commands, reusable logic, and hooks |
cypress.config.js | Cypress configuration file for base URL, timeouts, etc. |
5. Cypress Configuration (Optional Setup)
Update cypress.config.js to include project-specific settings:
const { defineConfig } = require('cypress') module.exports = defineConfig({ e2e: { baseUrl: 'http://localhost:3000', defaultCommandTimeout: 7000, viewportWidth: 1280, viewportHeight: 800, } })
6. Add Cypress Script to package.json
You can simplify commands by adding a script:
"scripts": { "cypress:open": "npx cypress open", "cypress:run": "npx cypress run" }
Run with:
npm run cypress:open
7. Launch the Test Runner with npx cypress open, select a browser and test file, then watch the tests run step-by-step in the browser.
Now, Cypress is installed, configured, and ready to run. You can start creating test cases in the e2e folder.
Steps to run your first Cypress Test
Once Cypress is installed, running your first test is easy. This section walks you through creating a basic test script that visits a webpage and performs a simple check.
Step 1: Open Cypress Test Runner
In your terminal, run:
npx Cypress open
Cypress opens in a browser window. You’ll see the project dashboard and sample test files in the /cypress/e2e folder.
Step 2: Create a New Test File
Navigate to the /cypress/e2e/ directory. Create a file named firstTest.cy.js.
Inside it, paste this code:
describe('My First Test', () => { it('Visits the Example Page and checks content', () => { cy.visit('https://example.cypress.io') cy.contains('type').click() // Check if the new URL includes '/commands/actions' cy.url().should('include', '/commands/actions') // Get an input, type into it and verify the value cy.get('.action-email') .type('test@example.com') .should('have.value', 'test@example.com') }) })
Step 3: Run the Test
- Return to the Cypress Test Runner.
- Click on firstTest.cy.js.
- Cypress launches the selected browser (default: Electron or Chrome) and executes the test with visual step tracking.
Step 4: View Test Output
You’ll see:
- A green checkmark for each passed command.
- Visual DOM snapshot after each command.
- URL change tracking.
- Input value verification.
Terminal log (for headless run):
Running: firstTest.cy.js My First Test ✓ Visits the Example Page and checks content (1.2s) 1 passing (1.2s)
Folder Structure of Cypress Framework
Once you launch Cypress using npx cypress open, it automatically generates a standard folder structure to help you organize tests efficiently.
Default Folder Structure
/cypress /e2e /fixtures /support /downloads (optional, generated after some tests) /node_modules /cypress.config.js /package.json
Here’s a breakdown of each folder:
1. /cypress/e2e – Test Specifications
This is where your test files go. Each .cy.js, .cy.ts, or .cy.jsx file defines a suite of test cases.
// /cypress/e2e/loginTest.cy.js describe('Login Page Test', () => { it('should display login form', () => { cy.visit('/login') cy.get('form').should('exist') }) })
2. /cypress/fixtures – Mock Test Data
Store test data (usually in .json format) for use across test cases.
Example: userData.json
{ "email": "test@example.com", "password": "test1234" }
Use in a test file:
cy.fixture('userData').then((user) => { cy.get('#email').type(user.email) cy.get('#password').type(user.password) })
3. /cypress/support – Reusable Code
- commands.js: Define custom Cypress commands here.
- e2e.js: Global setup code, runs before every test file.
Example from commands.js:
Cypress.Commands.add('login', (email, password) => { cy.get('#email').type(email) cy.get('#password').type(password) cy.get('button[type="submit"]').click() })
Use in test:
cy.login('user@example.com', 'securePass')
4. /cypress.config.js – Cypress Configuration
Central config file to set base URL, test timeouts, folder paths, etc.
Example:
const { defineConfig } = require('cypress') module.exports = defineConfig({ e2e: { baseUrl: 'https://example.com', defaultCommandTimeout: 10000 } })
5. /downloads – Optional Folder
Cypress generates this when your test includes file downloads. It stores downloaded files during test runs.
6. /node_modules and /package.json
Standard Node.js folders:
- node_modules: Contains all installed dependencies, including Cypress.
- package.json: Lists your dev dependencies and scripts.
Create Test File in Cypress
Here are the detailed steps on how to create test file in Cypress:
Step 1: Go to the /e2e Folder
Open the /cypress/e2e folder inside your Cypress project. This is where all test files live.
Use the command line or your code editor to create a new file.
For example:
touch loginTest.cy.js
Or in VS Code, right-click → New File → loginTest.cy.js.
Step 2: Write Your Test Code
Paste this into loginTest.cy.js:
describe('Login Page Tests', () => { it('should display login form on visit', () => { cy.visit('https://example.com/login') cy.get('form').should('exist') }) it('should allow user to login with valid credentials', () => { cy.get('#email').type('user@example.com') cy.get('#password').type('securePass123') cy.get('button[type="submit"]').click() cy.url().should('include', '/dashboard') }) })
Step 3: Run the Test
Use this command in your terminal:
npx Cypress open
Then click on loginTest.cy.js in the Cypress Test Runner. Cypress will open your browser and begin executing your test cases.
Step 4: Output Verification
You’ll see:
- Each action visualized in real-time.
- Green checkmarks next to successful steps.
- Detailed error logs (if any test fails).
Example terminal output (if run in headless mode):
Running: loginTest.cy.js Login Page Tests ✓ should display a login form on visit ✓ should allow the user to login with valid credentials 2 passing (2.1s)
Executing Cypress Test Cases Locally
Running Cypress tests on your local machine is quick and requires minimal setup. Cypress offers two local execution modes: headed and headless.
You can choose based on your need to view the browser UI or not.
1. Open Cypress in Interactive Mode (Headed)
This mode opens the Cypress Test Runner GUI, where you can run tests manually on a real browser.
Command:
npx Cypress open
What It Does:
- Opens the Cypress Test Runner window.
- Lists all test files inside /cypress/e2e.
- Lets you select a browser (Chrome, Edge, Firefox, or Electron).
- Runs tests with real-time visual feedback.
Output:
- Green ticks for passed tests.
- Red X for failed steps.
- Live DOM snapshot and network logs.
2. Run Tests in Headless Mode (Without UI)
Use this for faster execution or when integrating into CI pipelines. Tests run in the terminal without opening a browser UI.
Command:
npx cypress run
Optional Flags:
npx cypress run --spec "cypress/e2e/loginTest.cy.js" npx Cypress run --browser chrome
What It Does:
- Launches Electron by default unless you specify another browser.
- Executes all specs or the one you specify.
- Prints results in the terminal.
Cypress Testing on Real Browsers with BrowserStack
While local Cypress testing works during early development, it fails to replicate real user conditions.
BrowserStack Automate bridges the gap by offering seamless cloud-based testing on real browsers and devices.
Why BrowserStack Automate for Cypress:
- Real Device & Browser Coverage: Run Cypress tests on actual Windows, macOS, iOS, and Android devices, covering critical browser versions, screen sizes, and platforms.
- Parallel Execution: Speed up test cycles with parallel runs, reducing test time without compromising coverage.
- Effortless Integration: Set up in minutes using BrowserStack’s CLI and simple config file. Tests run on the cloud with real-time logs, video, and screenshots for easy debugging.
- Secure Testing: Test staging or internal builds via secure tunneling without needing to expose your app to the public web.
Also Read: How to reduce Testing Cycle Time?
Advantages of Cypress Web Testing
Cypress differentiates itself from other automation tools by addressing typical developer pain points with innovative architecture and an easy setup.
Here are some key advantages:
- Fast, Real-Time Execution: Runs in the browser with no network delays, offering instant feedback during development and CI.
- Auto-Wait and Retry: Automatically waits for elements and retries failed assertions, reducing flaky tests.
- Simple Setup: Install with one command. No complex configs or extra dependencies needed.
- Powerful Debugging: Get clear errors, step-by-step timelines, and live app state for faster issue resolution.
- Consistent Test Results: Runs inside the browser for stable, repeatable tests across all environments.
- CI-Friendly Dashboard: Works with popular CI tools and offers insights via logs, videos, and test history.
Disadvantages of Cypress Web Testing
Although Cypress has a number of advantages, it has its restrictions as well.
- Limited Browser Support: Works only with Chrome, Edge, and Firefox. No support for Safari or Internet Explorer.
- No Multi-Tab/Window Support: Can’t handle pop-ups, new tabs, or OAuth flows involving multiple windows.
- JavaScript-Only: Tests must be written in JavaScript or TypeScript, limiting non-JS teams.
- Cross-Origin Restrictions: Limited support for apps spanning multiple domains or iframes.
- No Mobile App Testing: Supports only web apps. Native mobile testing needs separate tools like Appium.
- Advanced Features Require Expertise: Features like stubbing and custom commands have a steeper learning curve.
- High Local Resource Usage: Running Cypress locally can slow machines, especially with large test suites. CI setups are recommended.
Best Practices for Cypress Web Testing
These best practices enhance test stability, minimize maintenance, and enable long-term scalability.
- Keep Tests Independent: Avoid test dependencies. Each test should run in isolation to ensure reliability.
- Use Fixtures for Data: Store test data in external JSON files to keep tests clean and reusable.
- Avoid Hardcoded Waits: Rely on Cypress’s built-in waiting and retries instead of using arbitrary timeouts.
- Organise with describe(): Group related tests and use clear, descriptive titles for better structure.
- Reset State Before Tests: Use beforeEach() to start with a clean state by clearing storage or reloading pages.
- Stub APIs with cy.intercept(): Mock external calls for speed and control over edge cases.
- Create Custom Commands: Use Cypress.Commands.add() for repeated actions like login to avoid duplication.
- Run in Both Modes: Use headless mode for CI and headed mode for debugging during development.
- Use Cypress Dashboard: Track test history, videos, and flaky tests across branches and teams.
- Maintain Test Suites: Review and refactor tests regularly to align with app changes.
Conclusion
Cypress is a robust tool for quick, predictable front-end testing. Its developer-oriented features, live debugging, and out-of-the-box CI integration give it an edge as a complete tool for today’s web applications.
For JavaScript-based app development teams, Cypress is a viable and scalable solution for confidently keeping test coverage high. In addition, BrowserStack enables you to test on real devices to ensure your app performs as expected.
Frequently Asked Questions
1. What is Cypress used for?
Cypress is a front-end testing framework for testing web applications on the modern web. It assists developers and QA teams with end-to-end, integration, and UI testing. It also has debugging tools and runs directly in the browser.
2. Which one is better: Cypress vs Selenium?
Both Cypress and Selenium are powerful, but they serve different needs. Cypress is useful for JavaScript applications and real-time browser tests. Selenium is more suited for testing against multiple devices and browsers, and your team works on various programming languages, such as Java, Python, or C#.
Useful Resources for Cypress
Understanding Cypress
- Cross Browser Testing with Cypress : Tutorial
- Run Cypress tests in parallel without Dashboard: Tutorial
- Handling Test Failures in Cypress A Comprehensive Guide
- Cypress Test Runner: Tutorial
- Handling Touch and Mouse events using Cypress
- Cypress Automation Tutorial
- CSS Selectors in Cypress
- Performance Testing with Cypress: A detailed Guide
- Cypress Best Practices for Test Automation
- Test React Native Apps with Cypress
- Cypress E2E Angular Testing: Advanced Tutorial
- Cypress Locators : How to find HTML elements
- Maximizing Web Security with Cypress: A Step-by-Step Guide
- Conditional Testing in Cypress: Tutorial
- Cypress Web Testing Framework: Getting Started
- Cypress Disable Test: How to use Skip and Only in Cypress
- What’s new in Cypress 10? How it will change your current testing requirements
Use Cases
- How to Record Cypress Tests? (Detailed Guide)
- How to run your first Visual Test with Cypress
- How to Fill and Submit Forms in Cypress
- How to Automate Localization Testing using Cypress
- How to run Cypress Tests in Chrome and Edge
- How to use Cypress App Actions?
- How to Run Cypress Tests for your Create-React-App Application
- How to Run Cypress Tests in Parallel
- How to handle Click Events in Cypress
- How to Test React using Cypress
- How to Perform Visual Testing for Components in Cypress
- How to run UI tests in Cypress
- How to test redirect with Cypress
- How to Perform Screenshot Testing in Cypress
- How to write Test Case in Cypress: (with testing example)
Tool Comparisons