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 testsit('test name', () => { ... }): Defines a testbeforeEach(() => { ... }): Runs before each testafterEach(() => { ... }): 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
describeblock, making tests hard to read and maintain. - Not using hooks like
beforeEachto 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
| Concept | Purpose | Example |
|---|---|---|
| describe | Group related tests | describe('Feature', () => { ... }) |
| it | Define a single test | it('does something', () => { ... }) |
| beforeEach | Run setup before each test | beforeEach(() => { cy.visit('/') }) |
| afterEach | Run cleanup after each test | afterEach(() => { /* cleanup */ }) |
| Folder structure | Organize tests by feature/page | cypress/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.