Learn Cypress in 10 DaysDay 1: Welcome to Cypress
Chapter 1Learn Cypress in 10 Days

Day 1: Welcome to Cypress

What You'll Learn Today

  • What E2E testing is and why it matters
  • The testing pyramid concept (Unit, Integration, E2E)
  • What Cypress is, its features, and advantages
  • Cypress vs Selenium comparison
  • Cypress architecture
  • Installation and initial setup
  • How to use the Cypress Test Runner

What Is E2E Testing?

When developing web applications, you need to verify behaviors like "Does clicking this button navigate to the correct page?" or "Does submitting a form actually save the data?" Checking all of this manually every time is tedious and error-prone.

E2E (End-to-End) testing is a testing approach that automates browser interactions to verify your entire application works correctly β€” just as a real user would experience it.

flowchart LR
    subgraph Manual["Manual Testing"]
        M1["Open the browser"]
        M2["Fill in the form"]
        M3["Click the button"]
        M4["Visually verify results"]
    end
    subgraph E2E["E2E Testing (Automated)"]
        E1["cy.visit()"]
        E2["cy.type()"]
        E3["cy.click()"]
        E4["cy.should() auto-verifies"]
    end
    M1 --> M2 --> M3 --> M4
    E1 --> E2 --> E3 --> E4
    style Manual fill:#f59e0b,color:#fff
    style E2E fill:#22c55e,color:#fff

Why Do We Need E2E Testing?

Problem How E2E Testing Helps
Manual testing is time-consuming Automated tests finish in minutes
Humans make mistakes Tests execute the same steps accurately every time
Regressions are hard to detect Automatically checks the entire app after every change
Cross-browser verification is tedious Can run automatically across multiple browsers
Verifying after late-night deployments Runs automatically in CI/CD pipelines

The Testing Pyramid

Software testing comes in several types depending on scope and purpose. The testing pyramid provides a systematic way to think about them.

flowchart TB
    subgraph Pyramid["Testing Pyramid"]
        E2E["E2E Tests\n(Few Β· High cost Β· High confidence)"]
        INT["Integration Tests\n(Moderate)"]
        UNIT["Unit Tests\n(Many Β· Low cost Β· Fast)"]
    end
    E2E --> INT --> UNIT
    style E2E fill:#ef4444,color:#fff
    style INT fill:#f59e0b,color:#fff
    style UNIT fill:#22c55e,color:#fff
Test Type Scope Speed Cost Example
Unit Tests Individual functions/components Fast Low Testing input/output of a calculation function
Integration Tests Multiple components working together Moderate Moderate Testing API and database interaction
E2E Tests The entire application Slow High User login flow

Testing Pyramid Principles

  • Write the most unit tests: They are fast and stable
  • Limit E2E tests to critical flows: They are slow to run and expensive to maintain
  • Balance is key: Each layer of tests complements the others to ensure quality

What Is Cypress?

Cypress is an E2E testing framework built for modern web applications. Development began in 2014 by Brian Mann, with the goal of fundamentally solving the problems that plagued traditional Selenium-based testing tools.

Key Features of Cypress

  1. Runs directly in the browser: Test code executes within the same browser as your application
  2. Auto-waiting: Automatically waits for elements to appear and animations to complete
  3. Time-travel debugging: Review each test step through DOM snapshots
  4. Real-time reloading: Tests re-run automatically when you save a test file
  5. Stubs and spies: Easily mock and intercept network requests
flowchart TB
    subgraph Features["Cypress Features"]
        F1["Auto-waiting"]
        F2["Time-travel\nDebugging"]
        F3["Real-time\nReloading"]
        F4["Network\nStubbing"]
        F5["Screenshots\n& Video Recording"]
    end
    style Features fill:#3b82f6,color:#fff

Cypress vs Selenium

Let's compare Cypress with Selenium, the long-established E2E testing tool.

flowchart TB
    subgraph Selenium["Selenium Architecture"]
        S_TEST["Test Code"]
        S_DRIVER["WebDriver"]
        S_BROWSER["Browser"]
        S_APP["Application"]
    end
    subgraph Cypress["Cypress Architecture"]
        C_TEST["Test Code"]
        C_BROWSER["Browser (Same Process)"]
        C_APP["Application"]
    end
    S_TEST --> S_DRIVER --> S_BROWSER --> S_APP
    C_TEST --> C_BROWSER
    C_BROWSER --> C_APP
    style Selenium fill:#f59e0b,color:#fff
    style Cypress fill:#3b82f6,color:#fff

Selenium places a WebDriver layer between the test code and the browser, while Cypress executes test code directly inside the browser. This architectural difference brings numerous advantages.

Aspect Selenium Cypress
Architecture Controls the browser externally via WebDriver Runs directly inside the browser
Setup Requires installing and managing WebDriver Just npm install
Languages Java, Python, C#, Ruby, JavaScript, etc. JavaScript only
Browser Support Chrome, Firefox, Safari, Edge, IE Chrome, Firefox, Edge, Electron
Auto-waiting Must write manual waits Built-in auto-waiting
Debugging Difficult (external process) Time-travel debugging
Network Control Requires external proxy Built-in interception
Execution Speed Relatively slow Fast
Learning Curve Steep Gentle

When Cypress Is a Good Fit

  • Testing modern JavaScript frameworks (React, Vue, Angular, etc.)
  • Frontend-focused E2E testing
  • Teams proficient in JavaScript
  • When fast feedback loops are essential

When Selenium Is a Better Fit

  • Multi-language support is required
  • Safari or legacy browser testing is mandatory
  • Large-scale cross-browser testing is needed

Cypress Architecture

Cypress has a fundamentally different architecture from traditional testing tools.

flowchart TB
    subgraph Browser["Browser (Electron / Chrome)"]
        subgraph CypressRunner["Cypress Test Runner"]
            SPEC["Test Files\n(spec.cy.js)"]
            CMD["Cypress Commands\n(cy.get, cy.click, etc.)"]
        end
        subgraph AppFrame["Application iframe"]
            APP["Application\nUnder Test"]
            DOM["DOM"]
        end
        CMD --> DOM
    end
    subgraph NodeServer["Node.js Server"]
        PROXY["Proxy"]
        FILE["File System"]
        NET["Network Control"]
    end
    Browser <--> NodeServer
    style Browser fill:#3b82f6,color:#fff
    style NodeServer fill:#8b5cf6,color:#fff
    style CypressRunner fill:#22c55e,color:#fff
    style AppFrame fill:#f59e0b,color:#fff

Architecture Highlights

  1. Test code runs inside the browser: Since it shares the same execution environment as the application, it has direct access to the DOM
  2. Node.js server handles the backend: File operations and network control are processed by a Node.js process
  3. Proxy-based network control: All HTTP requests pass through a proxy, enabling request interception and mocking

Installation and Setup

Prerequisites

  • Node.js 18 or later installed
  • npm or yarn available

Installation Steps

# Create a project directory
mkdir my-cypress-project
cd my-cypress-project

# Initialize package.json
npm init -y

# Install Cypress
npm install cypress --save-dev

Once installation is complete, the executable is placed at node_modules/.bin/cypress.

First Launch

# Launch the Cypress Test Runner
npx cypress open

On the first launch, Cypress automatically creates the following directory structure:

my-cypress-project/
β”œβ”€β”€ cypress/
β”‚   β”œβ”€β”€ e2e/              # Directory for test files
β”‚   β”œβ”€β”€ fixtures/         # Test data (JSON, etc.)
β”‚   β”œβ”€β”€ support/          # Custom commands and global configuration
β”‚   β”‚   β”œβ”€β”€ commands.js   # Custom command definitions
β”‚   β”‚   └── e2e.js        # Global configuration for E2E tests
β”‚   └── downloads/        # Downloaded file storage
β”œβ”€β”€ cypress.config.js     # Cypress configuration file
└── package.json

Basic cypress.config.js Configuration

The Cypress configuration file is cypress.config.js. Let's look at the key settings.

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    // Base URL for the application under test
    baseUrl: 'http://localhost:3000',

    // Test file pattern
    specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',

    // Viewport size
    viewportWidth: 1280,
    viewportHeight: 720,

    // Screenshot on test failure
    screenshotOnRunFailure: true,

    // Video recording of test runs
    video: false,

    // Timeout settings (milliseconds)
    defaultCommandTimeout: 4000,
    pageLoadTimeout: 60000,

    // Retry settings
    retries: {
      runMode: 2,    // Retries when running cypress run
      openMode: 0,   // Retries when running cypress open
    },

    setupNodeEvents(on, config) {
      // Register Node.js event listeners
    },
  },
})

Key Configuration Options

Option Default Description
baseUrl null Base URL for cy.visit('/')
viewportWidth 1000 Browser width
viewportHeight 660 Browser height
defaultCommandTimeout 4000 Command timeout (ms)
pageLoadTimeout 60000 Page load timeout (ms)
video false Video recording of test runs
screenshotOnRunFailure true Screenshot on failure
retries { runMode: 0, openMode: 0 } Number of test retries

The Cypress Test Runner

Launching the Test Runner with npx cypress open opens a GUI.

Main Components of the Test Runner

  1. Test type selection screen: Choose between E2E Testing or Component Testing
  2. Browser selection: Choose the browser for running tests (Chrome, Firefox, Edge, Electron)
  3. Test file list: Displays available test files
  4. Test execution view: Command log on the left, application preview on the right

Running in Headless Mode

In CI/CD environments, you run tests without a GUI.

# Run all tests in headless mode
npx cypress run

# Run a specific test file
npx cypress run --spec "cypress/e2e/login.cy.js"

# Run with a specific browser
npx cypress run --browser chrome

Summary

Concept Description
E2E Testing Tests that automate user interactions to verify the entire application
Testing Pyramid A three-layer structure: Unit β†’ Integration β†’ E2E. Write more tests at lower layers
Cypress A modern E2E testing framework that runs directly inside the browser
Auto-waiting Cypress automatically waits for elements to appear and animations to complete
Time Travel A debugging feature that lets you inspect DOM snapshots at each test step
cypress.config.js The Cypress configuration file for setting baseUrl, timeouts, etc.

Key Points

  1. E2E testing is essential for automating manual tests and preventing regressions
  2. Cypress runs directly in the browser, enabling fast and stable tests
  3. The auto-waiting feature eliminates the need for sleep or wait calls in test code

Practice Exercises

Exercise 1: Basic

Describe the three layers of the testing pyramid and provide an example of what kind of test belongs at each layer.

Exercise 2: Applied

Explain the architectural differences between Cypress and Selenium, and list three advantages that Cypress's architecture provides.

Challenge Exercise

Set up Cypress in a new project and add the following settings to cypress.config.js: set the base URL to http://localhost:8080, the viewport size to 1920x1080, and the default command timeout to 10 seconds.


References


Next Up: In Day 2, we'll learn about writing your first test. You'll understand the structure of test files and write an actual E2E test for a Todo app.