0
0
CypressHow-ToBeginner ยท 4 min read

How to Organize Tests in Cypress for Clean and Scalable Automation

In Cypress, organize tests by grouping related tests inside describe blocks and placing test files in meaningful folders under cypress/e2e. Use before, beforeEach, after, and afterEach hooks inside describe blocks to share setup and cleanup code.
๐Ÿ“

Syntax

Use describe to group related tests. Inside, use it for individual test cases. Hooks like beforeEach run code before each test in the group.

  • describe('group name', () => { ... }): Groups tests
  • it('test name', () => { ... }): Defines a test
  • beforeEach(() => { ... }): Runs before each test
  • afterEach(() => { ... }): Runs after each test

Organize test files in folders inside cypress/e2e to separate features or pages.

javascript
describe('Login feature', () => {
  beforeEach(() => {
    cy.visit('/login')
  })

  it('should show error on invalid credentials', () => {
    cy.get('#username').type('wrong')
    cy.get('#password').type('wrong')
    cy.get('button[type=submit]').click()
    cy.contains('Invalid username or password').should('be.visible')
  })

  it('should login successfully with valid credentials', () => {
    cy.get('#username').type('user')
    cy.get('#password').type('pass')
    cy.get('button[type=submit]').click()
    cy.url().should('include', '/dashboard')
  })
})
๐Ÿ’ป

Example

This example shows how to organize tests for a login page using describe blocks and hooks. Tests are grouped logically, and setup code runs before each test.

javascript
// File: cypress/e2e/auth/login.cy.js

describe('Login Page Tests', () => {
  beforeEach(() => {
    cy.visit('/login')
  })

  it('displays login form', () => {
    cy.get('form#loginForm').should('be.visible')
  })

  it('fails login with wrong password', () => {
    cy.get('#username').type('testuser')
    cy.get('#password').type('wrongpass')
    cy.get('button[type=submit]').click()
    cy.contains('Invalid username or password').should('be.visible')
  })

  it('logs in successfully', () => {
    cy.get('#username').type('testuser')
    cy.get('#password').type('correctpass')
    cy.get('button[type=submit]').click()
    cy.url().should('include', '/dashboard')
  })
})
Output
3 tests passed (Login Page Tests)
โš ๏ธ

Common Pitfalls

Common mistakes when organizing Cypress tests include:

  • Putting too many unrelated tests in one describe block, making tests hard to read and maintain.
  • Not using hooks like beforeEach to avoid repeating setup code.
  • Scattering test files without a clear folder structure, causing confusion.
  • Using overly broad selectors that break easily.

Keep tests focused, use hooks for setup, and organize files by feature or page.

javascript
// Wrong: All tests in one block without hooks

describe('All tests', () => {
  it('test 1', () => {
    cy.visit('/page1')
    // test steps
  })

  it('test 2', () => {
    cy.visit('/page2')
    // test steps
  })
})

// Right: Separate describe blocks and use hooks

describe('Page 1 tests', () => {
  beforeEach(() => cy.visit('/page1'))
  it('test 1', () => { /* test steps */ })
})

describe('Page 2 tests', () => {
  beforeEach(() => cy.visit('/page2'))
  it('test 2', () => { /* test steps */ })
})
๐Ÿ“Š

Quick Reference

ConceptPurposeExample
describeGroup related testsdescribe('Feature', () => { ... })
itDefine a single testit('does something', () => { ... })
beforeEachRun setup before each testbeforeEach(() => { cy.visit('/') })
afterEachRun cleanup after each testafterEach(() => { /* cleanup */ })
Folder structureOrganize tests by feature/pagecypress/e2e/login/login.cy.js
โœ…

Key Takeaways

Group related tests inside describe blocks for clarity and structure.
Use beforeEach and afterEach hooks to share setup and cleanup code.
Organize test files in folders by feature or page under cypress/e2e.
Avoid mixing unrelated tests in one describe block to keep tests maintainable.
Use clear, stable selectors and keep tests focused on one behavior.