Mastering Cypress Test Setup and Teardown with before:run
and after:run
Cypress is a powerful tool for end-to-end testing, but when it comes to managing resources dynamically, such as creating and cleaning up test data, leveraging before:run
and after:run
hooks in cypress.config.ts
can simplify and automate these processes. This article explains how to use these hooks to handle test setup and teardown efficiently.
Why Use before:run
and after:run
Hooks?
before:run
:- Executes once before the test suite starts.
- Ideal for setting up resources, like creating test projects or fetching authentication tokens.
after:run
:- Executes once after the test suite completes.
- Perfect for cleaning up resources, such as deleting test projects or data.
Hypothetical Scenario: Testing a User Management System
Imagine you’re testing a user management system. Your tests require:
- A test user to exist before running the suite.
- The test user to be deleted after the tests are completed.
We will use before:run
to create the user and after:run
to delete it.
1. Creating Resources with before:run
In this example, the before:run
hook will:
- Fetch an authentication token to interact with the system’s API.
- Create a test user using the token.
- Store the
userId
for cleanup.
import { defineConfig } from ‘cypress’;
import axios from ‘axios’;
import fs from ‘fs’;
import path from ‘path’;// Helper to fetch an authentication token
async function getAuthToken(): Promise<string> {
const apiUrl = ‘https://api.example.com/login';
const credentials = { username: ‘testAdmin’, password: ‘password123’ };const response = await axios.post(apiUrl, credentials, {
headers: { ‘Content-Type’: ‘application/json’ },
});if (response.status === 200 && response.data.token) {
return response.data.token;
} else {
throw new Error(‘Failed to fetch auth token’);
}
}// Helper to create a test user
async function createTestUser(authToken: string): Promise<string> {
const apiUrl = ‘https://api.example.com/users';
const userDetails = { name: ‘Test User’, email: ‘testuser@example.com’, role: ‘tester’ };const response = await axios.post(apiUrl, userDetails, {
headers: {
Authorization: `Bearer ${authToken}`,
‘Content-Type’: ‘application/json’,
},
});if (response.status === 201 && response.data.id) {
return response.data.id; // Return the created user’s ID
} else {
throw new Error(‘Failed to create test user’);
}
}export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
let authToken: string;
let userId: string;on(‘before:run’, async () => {
console.log(‘Setting up resources before tests…’);
try {
// Step 1: Get Auth Token
authToken = await getAuthToken();
console.log(‘Auth Token:’, authToken);// Step 2: Create Test User
userId = await createTestUser(authToken);
console.log(‘Test User Created with ID:’, userId);
} catch (error) {
console.error(‘Error during setup:’, error.message);
throw error;
}
});// Cleanup resources after tests
on(‘after:run’, async () => {
console.log(‘Cleaning up resources after tests…’);
try {// Step 1: Delete Test User
const apiUrl = `https://api.example.com/users/${userId}`;
await axios.delete(apiUrl, {
headers: {
Authorization: `Bearer ${authToken}`,
},
});console.log(‘Test User Deleted Successfully’);
} catch (error) {
console.error(‘Error during cleanup:’, error.message);
}
});return config;
},
},
});
2. Cleaning Up Resources with after:run
The after:run
hook reads the userId
stored into variable and deletes the user using the API. This ensures a clean slate for subsequent test runs.
The before:run
and after:run
hooks in Cypress provide powerful lifecycle events to manage test setups and teardowns. By automating resource creation and cleanup, you can maintain a clean test environment and reduce manual effort.