Cypress
Cypress is a powerful and user-friendly end-to-end testing framework designed for modern web applications. It allows developers and QA engineers to write reliable and fast tests for web interfaces.
Key Features
- Easy Installation: Install Cypress using npm or yarn.
- Time Travel: Debug tests by replaying snapshots of previous test states.
- Automatic Waiting: No need for manual waits or retries; Cypress automatically waits for commands and assertions.
- Real-Time Reloads: Instantly re-runs tests upon saving changes.
- Cross-Browser Testing: Supports multiple browsers like Chrome, Firefox, and Edge.
Installation
Prerequisites:
- Node.js (Ensure you have Node.js installed.)
Steps:
- Initialize your project:
npm init -y - Install Cypress:
npm install cypress --save-dev
Open Cypress:
npx cypress open
This command launches the Cypress Test Runner.
Writing Your First Test
Folder Structure:
Cypress stores tests in the cypress/e2e directory by default.
Example Test:
Create a file named example.cy.js in the cypress/e2e folder:
describe('My First Test', () => {
it('Visits the Cypress website', () => {
cy.visit('https://www.cypress.io');
cy.contains('Get Started').click();
cy.url().should('include', '/getting-started');
});
});
Run the Test:
Execute the test by selecting it in the Cypress Test Runner.
Organizing Tests
Folder Structure
Cypress provides a default folder structure, which you can customize as needed. A well-organized structure ensures your tests are easy to navigate and maintain.
Default Folder Structure:
cypress/
├── e2e/ # Contains your test files
├── fixtures/ # Stores static test data (e.g., JSON files)
├── support/ # Contains reusable commands and configurations
├── downloads/ # Stores files downloaded during tests
├── screenshots/ # Captures screenshots of test failures
└── videos/ # Stores videos of test runs
Recommended Test Structure:
-
By Feature: Group tests by application features.
cypress/e2e/
├── auth/
│ ├── login.cy.js
│ └── signup.cy.js
├── dashboard/
│ ├── view.cy.js
│ └── edit.cy.js
└── settings/
├── profile.cy.js
└── preferences.cy.js -
By Type: Group tests by type (e.g., smoke, regression, integration).
cypress/e2e/
├── smoke/
│ ├── basic-functionality.cy.js
├── regression/
│ ├── all-tests.cy.js
└── integration/
├── api-tests.cy.js
Page Object Model (POM)
The Page Object Model is a design pattern that promotes reusability and maintainability.
Example:
-
Create a
page-objectsfolder:cypress/support/page-objects/
├── loginPage.js
├── dashboardPage.js
└── settingsPage.js -
Define reusable functions in
loginPage.js:class LoginPage {
visit() {
cy.visit('/login');
}
enterUsername(username) {
cy.get('#username').type(username);
}
enterPassword(password) {
cy.get('#password').type(password);
}
submit() {
cy.get('button[type="submit"]').click();
}
}
export default new LoginPage(); -
Use the
LoginPageobject in your test:import LoginPage from '../support/page-objects/loginPage';
describe('Login Tests', () => {
it('Logs in successfully', () => {
LoginPage.visit();
LoginPage.enterUsername('testUser');
LoginPage.enterPassword('password123');
LoginPage.submit();
cy.url().should('include', '/dashboard');
});
});
Custom Commands
Place reusable commands in cypress/support/commands.js to keep tests concise.
Example:
Add a custom command:
Cypress.Commands.add('login', (username, password) => {
cy.visit('/login');
cy.get('#username').type(username);
cy.get('#password').type(password);
cy.get('button[type="submit"]').click();
});
Use the custom command in a test:
describe('Login Tests', () => {
it('Logs in successfully', () => {
cy.login('testUser', 'password123');
cy.url().should('include', '/dashboard');
});
});
Use Tags for Test Categorization
Use tags to categorize and filter tests when running them.
Example:
describe('Smoke Tests', { tags: '@smoke' }, () => {
it('Basic functionality', () => {
// Test code
});
});
Run only tagged tests:
npx cypress run --env TAGS="@smoke"
Fixture Files
Use cypress/fixtures to store static test data like JSON files.
Example:
user.json in cypress/fixtures:
{
"username": "testUser",
"password": "password123"
}
Access fixtures in a test:
describe('Login Tests', () => {
it('Logs in using fixture data', () => {
cy.fixture('user').then((user) => {
cy.visit('/login');
cy.get('#username').type(user.username);
cy.get('#password').type(user.password);
cy.get('button[type="submit"]').click();
cy.url().should('include', '/dashboard');
});
});
});
Best Practices
- Use Page Objects: Organize reusable page-specific functions and selectors.
- Avoid Flaky Tests: Ensure tests are independent and do not rely on external systems.
- Leverage Cypress Commands: Use custom commands for repetitive actions.
- Run Tests in CI/CD: Integrate Cypress with CI/CD pipelines for continuous testing.
Resources
Cypress is an essential tool for modern web application testing, offering speed, reliability, and ease of use. Begin your testing journey with Cypress today!