w3resource

Environment Variables


This tutorial will cover the benefits of environment variables as well as how you can set them up.

Why do we need an environment variable?

Environment variables are very useful when:

  • The values are different across developer machines.
  • The values are different across multiple environments: (dev, staging, qa, prod)
  • The values are highly dynamic and change frequently.

You can easily change the environment variables, especially when you are running in CI.

Rather than hardcoding values in your tests as shown below:

cy.request('https://api.sample.corp') // this request will break on other environments

you can move this into a Cypress environment variable:

cy.request(Cypress.env('EXTERNAL_API')) // this will point to a dynamic env var

Using ‘baseUrl’

Usually, environment variables are great when it comes to pointing to external services and servers, or when you are storing passwords and other credentials.

However, you should not use environment variables to points to the origin and domain under test. You should use baseUrl, instead of environment variables.

The cy.visit() and cy.request() commands will be prefixed automatically with tins value- this eliminates the need to specify them.

The baseUrl can be set in your configuration file (cypress.json by default) and then you will be able to set an environment variable in your OS to override it as shown below:

CYPRESS_BASE_URL=https://staging.app.com cypress run

Settting

There are 5 different ways that you can set environment variables. Each of them has a slightly different use case.

The five ways are as listed below:

  • Set in your configuration file
  • Create a `cypress.env.json`
  • Export as `CYPRESS_*`
  • Pass in the CLI as `--env`
  • Set an environment variable inside your plugins.
  • Finally, you can set an environment variable within test configuration.

You should not feel obligated to pick just one method. It is a common to use one strategy during local development and use another when you are running in CI.

When you run your tests are running, you can use the Cypress.env function to access the values of your environment variables.

Option #1 configuration file

Any key/value pair that you set in your configuration file (cypress.json by default) under the env key will become an environment variable.

{
  "projectId": "128076ed-9868-4e98-9cef-98dd7a705d75",
  "env": {
    "foo": "bar",
    "some": "value"
  }
}

Test file

Cypress.env()      // {foo: 'bar', some: 'value'}
Cypress.env('foo')  // 'bar'
Cypress.env('some') // 'value'

Overview

Benefits

This option is great for values that need to be checked into source control and remain the same on all machines.

Downsides

The downside of this option is that it only works for values that should be the same across all machines.

Option #2 cypress.env.json

Alternatively, you can decide to create your own cypress.env.json file that Cypress will automatically. The values in this file will overwrite conflicting environment variables in your configuration file (cypress.json by default).

This is a very useful strategy because, if you add cypress.env.json to your .gitignore file, the values in the file can be different for each developer machine.

{
  "host": "aaronvikta.dev.local",
  "api_server": "http://localhost:8080/api/v1/"
}

From test file

Cypress.env()          // {host: 'aaronvikta.dev.local', api_server: 'http://localhost:8080/api/v1'}
Cypress.env('host')       // 'aaronvikta.dev.local'
Cypress.env('api_server') // 'http://localhost:8080/api/v1/'

Overview

Benefits

  • This option provides a dedicated file just for environment variables.
  • It will enable you to generate this file from other build processes.
  • The values can be different on each machine (if not checked into source control).
  • This option supports nested fields (objects), e.g. { testUser: { name: '...', email: '...' } }.

Downsides

  • This is another file you have to deal with.
  • It can be an overkill for 1 or 2 environment variables.

Option #3: CYPRESS_*

Every environment variable on your machine that starts with either CYPRESS_ or cypress_ will automatically be added and made available to you.

All the conflicting values will override values from your configuration file (cypress.json by default) and cypress.env.json files.

Cypress strips off the CYPRESS_ when adding your environment variables.

The environment variable CYPRESS_INTERNAL_ENV key is reserved and must not be set.

Export cypress env variables from the command line:

export CYPRESS_HOST=aryan.dev.local
export cypress_api_server=http://localhost:8080/api/v1/

In test file

Cypress.env()         // {HOST: 'aryan.dev.local', api_server: 'http://localhost:8080/api/v1'}
Cypress.env('HOST')       // 'aryan.dev.local'
Cypress.env('api_server') // 'http://localhost:8080/api/v1/'

Overview:

Benefits

  • This option quickly exports some values.
  • This can be stored in your bash_profile.
  • It allows for dynamic values between different machines.
  • It is especially useful for CI environments.

Downsides

  • With this option, it is not as obvious where values come from versus the other options.
  • There is no support for nested fields.

Option #4: --env

you can also pass in environment variables as options when using the CLI tool.

The values here will overwrite all other conflicting environment variables.

You can use the --env argument in your cypress run.

You must use comma to separate multiple values and not a space.

From the command line or CI, you can run:

cypress run --env host=johndoe.dev.local,api_server=http://localhost:8080/api/v1

Test file:

Cypress.env()         // {host: 'johndoe.dev.local', api_server: 'http://localhost:8080/api/v1'}
Cypress.env('host')       // 'johndoe.dev.local'
Cypress.env('api_server') // 'http://localhost:8080/api/v1/'

Overview

Benefits

  • It does not require any changes to files or configuration.
  • It is more clear where environment variables come from.
  • It allows for dynamic values between different machines.
  • It will overwrite all other forms of setting env variables.

Downsides

  • It is a pain to write the --env options everywhere you use Cypress.
  • It has no support for nested fields.

Option #5: Plugins

Rather than setting environment variables in a file, you can also use plugins to dynamically set them with Node code. This will enable you to do things like use fs and read off configuration values and dynamically change them.

Overview

Benefits

  • This option offers the most amount of flexibility
  • This option gives you the ability to manage configuration however you’d like

Downsides

  • It will require knowledge of writing in Node
  • More challenging

Option #6: Test Configuration

The environment variables for specific suites or test can be set by passing the env values to the test configuration.

Suite of test configuration

// change the environment variable for single suite of tests

'''describe('test against the Spanish site', {
  env: {
    language: 'es'
  }
}, () => {
  it('the site will display Spanish', () => {
    cy.visit(`https://docs.cypress.io/${Cypress.env('language')}/`)
    cy.contains('?Por qu? Cypress?')
  })
})'''

Single test configuration

// change the environment variable for single test

'''it('perform a smoke test on the development api', {
  env: {
    api: 'https://dev.myapi.com'
  }
}, () => {
  cy.request(Cypress.env('api')).its('status').should('eq', 200)
})

// change the environment variable for single test
it('perform a smoke test on the staging api', {
  env: {
    api: 'https://staging.myapi.com'
  }
}, () => {
  cy.request(Cypress.env('api')).its('status').should('eq', 200)
})'''

Overview

Benefits

  • This will only take effect for duration of suite or test.
  • More clear where environment variables come from.
  • Allows for dynamic values between tests

Overriding Configuration

In the case where your environment variables match a standard configuration key, then rather than setting an environment variable, they will instead override the configuration value.

Change the baseUrl configuration value / that is not set env var in Cypress.env()

'''export CYPRESS_BASE_URL=http://localhost:8081'''

'foo' does not match config / sets env var in Cypress.env()

'''export CYPRESS_FOO=bar'''