You can run Cypress tests against multiple environments by reconfiguring the baseUrl property in your cypress.config.js file.
Let’s see this in action. Imagine you have a cypress.config.js file that looks like this:
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000', // Default to development
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
And your Cypress test file might look like this:
describe('Login Feature', () => {
it('should allow a user to log in', () => {
cy.visit('/login'); // This will go to http://localhost:3000/login
cy.get('#username').type('testuser');
cy.get('#password').type('password123');
cy.get('button[type="submit"]').click();
cy.url().should('include', '/dashboard');
});
});
When you run npx cypress run, Cypress will execute the tests against http://localhost:3000.
To run against a staging environment, you’d change your configuration:
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'https://staging.yourapp.com', // Staging environment
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
Now, running npx cypress run will point your tests to https://staging.yourapp.com.
The baseUrl setting is the cornerstone of how Cypress interacts with your application’s URLs. When you use commands like cy.visit('/some/path'), Cypress automatically prepends the baseUrl to construct the full URL. This is crucial for ensuring your tests are targeting the correct instance of your application, whether it’s local development, a staging server, a production environment, or any other deployment.
You can also leverage environment variables to manage your baseUrl dynamically. This is a much more robust approach than manually editing the cypress.config.js file.
First, create a .env file in your project’s root directory (or use a dedicated .env management tool).
.env.development:
CYPRESS_BASE_URL=http://localhost:3000
.env.staging:
CYPRESS_BASE_URL=https://staging.yourapp.com
.env.production:
CYPRESS_BASE_URL=https://yourapp.com
Then, modify your cypress.config.js to read from these environment variables. You’ll need to install dotenv: npm install --save-dev dotenv.
require('dotenv').config(); // Load environment variables
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: process.env.CYPRESS_BASE_URL || 'http://localhost:3000', // Default to local if not set
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
To run tests against a specific environment, you’ll set the CYPRESS_BASE_URL environment variable before running Cypress.
For example, on Linux/macOS:
CYPRESS_BASE_URL=https://staging.yourapp.com npx cypress run
Or, if you’re using .env files and the dotenv package, you can specify which .env file to load. Many CI/CD pipelines support setting environment variables directly. If you’re running locally and want to explicitly load a .env file, you can do something like this:
# Load development environment
export NODE_ENV=development
npx cypress run
# Load staging environment
export NODE_ENV=staging
npx cypress run
And in your cypress.config.js:
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: process.env.CYPRESS_BASE_URL || 'http://localhost:3000',
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
This setup allows you to easily switch between environments without modifying your core test code. Your tests remain generic, referencing relative paths (e.g., /login, /dashboard), and the baseUrl configuration dictates where these paths are appended.
A common pattern is to have a default baseUrl for local development and then override it in your CI/CD pipeline for staging and production deployments. For instance, in GitHub Actions, you might set it in your workflow file:
jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install dependencies
run: npm install
- name: Run Cypress tests on staging
uses: cypress-io/github-action@v5
with:
browser: chrome
env: CYPRESS_BASE_URL=https://staging.yourapp.com
The env property within the Cypress GitHub Action allows you to inject environment variables directly into the Cypress execution context.
When Cypress starts, it reads the baseUrl from its configuration. If it finds an environment variable like CYPRESS_BASE_URL, it will use that value. If not, it falls back to the value defined directly in cypress.config.js. This hierarchical approach provides flexibility.
The actual mechanism is that Cypress’s internal cy.visit() command, when given a relative path (like /login), constructs the full URL by concatenating the baseUrl and the provided path. For example, if baseUrl is http://localhost:3000 and cy.visit('/login') is called, Cypress effectively executes new URL('/login', 'http://localhost:3000').toString(), resulting in http://localhost:3000/login.
The next logical step is to parameterize other configuration values, not just the baseUrl, using environment variables.