Environment-specific настройки

В автоматизированном тестировании приложений на JavaScript одной из ключевых задач является конфигурирование тестов под различные среды. Cypress предоставляет гибкие механизмы для работы с environment-specific параметрами, позволяя адаптировать тесты под локальную разработку, staging, production или другие окружения без изменения кода тестов.


Конфигурация через cypress.config.js

Файл cypress.config.js является центральным местом управления настройками Cypress. В нём можно определить глобальные параметры, а также параметры для конкретных окружений.

Пример базовой конфигурации:

const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    env: {
      apiUrl: 'http://localhost:5000/api',
      username: 'testuser',
      password: 'password123'
    },
    setupNodeEvents(on, config) {
      // node события
    }
  }
});
  • baseUrl — адрес приложения, к которому будут выполняться запросы.
  • env — объект для хранения environment-specific переменных, таких как URL API, логины, токены и другие параметры.
  • setupNodeEvents — функция для добавления кастомных событий Node.js, например, для логирования или модификации конфигурации во время выполнения тестов.

Разделение окружений

Cypress позволяет создавать отдельные конфигурации для разных сред. Это достигается через комбинацию cypress.config.js и специальных файлов переменных окружения, либо через командную строку.

Пример запуска тестов с определённой средой:

npx cypress run --env ENV=staging

В конфигурации можно использовать условные блоки:

const { defineConfig } = require('cypress');

const environment = process.env.ENV || 'development';

const envConfig = {
  development: {
    baseUrl: 'http://localhost:3000',
    apiUrl: 'http://localhost:5000/api'
  },
  staging: {
    baseUrl: 'https://staging.example.com',
    apiUrl: 'https://staging-api.example.com'
  },
  production: {
    baseUrl: 'https://example.com',
    apiUrl: 'https://api.example.com'
  }
};

module.exports = defineConfig({
  e2e: {
    baseUrl: envConfig[environment].baseUrl,
    env: {
      apiUrl: envConfig[environment].apiUrl
    }
  }
});

Такой подход позволяет одним тестовым кодом покрывать несколько окружений, просто изменяя параметр ENV.


Использование переменных окружения в тестах

Переменные, определённые через env или командную строку, доступны внутри тестов с помощью метода Cypress.env():

describe('API тесты', () => {
  it('Проверка получения данных', () => {
    const apiUrl = Cypress.env('apiUrl');

    cy.request(`${apiUrl}/users`)
      .its('status')
      .should('eq', 200);
  });
});

Особенности:

  • Cypress.env('имя') возвращает значение переменной.
  • Если переменная не определена в конфигурации, можно задавать её через CLI или файл .env.
  • Это позволяет использовать одни и те же тесты для разных сред без изменения исходного кода.

Работа с .env файлами

Для упрощения управления конфиденциальными данными и различными окружениями часто применяются .env файлы совместно с библиотекой dotenv.

Пример структуры:

.env.development
.env.staging
.env.production

Содержание файла .env.staging:

API_URL=https://staging-api.example.com
USERNAME=staging_user
PASSWORD=staging_pass

И подключение в cypress.config.js:

require('dotenv').config({ path: `.env.${process.env.ENV}` });

module.exports = defineConfig({
  e2e: {
    baseUrl: process.env.BASE_URL,
    env: {
      apiUrl: process.env.API_URL,
      username: process.env.USERNAME,
      password: process.env.PASSWORD
    }
  }
});

Этот способ гарантирует разделение секретов и конфигурации окружений и исключает их хардкод в тестах.


Динамическое изменение конфигурации во время тестов

Cypress предоставляет возможность модифицировать настройки во время выполнения через Cypress.config() и Cypress.env().

Пример:

Cypress.config('baseUrl', 'https://new-environment.example.com');
Cypress.env('apiUrl', 'https://new-api.example.com');

Это полезно для подмены URL, токенов или таймаутов без изменения глобальной конфигурации.


Настройка таймаутов и повторов для разных окружений

Разные среды могут иметь разные скорости отклика, поэтому важно настраивать таймауты и стратегию повторов через конфигурацию:

const envTimeouts = {
  development: { defaultCommandTimeout: 4000 },
  staging: { defaultCommandTimeout: 8000 },
  production: { defaultCommandTimeout: 10000 }
};

module.exports = defineConfig({
  e2e: {
    baseUrl: envConfig[environment].baseUrl,
    defaultCommandTimeout: envTimeouts[environment].defaultCommandTimeout
  }
});

Таким образом, тесты станут более устойчивыми к задержкам и нестабильности среды, что критично для интеграционных и end-to-end сценариев.


Использование environment-specific тестовых данных

Для разных окружений часто требуется разный набор данных:

const testData = {
  development: { userId: 1 },
  staging: { userId: 101 },
  production: { userId: 1001 }
};

describe('Проверка данных пользователя', () => {
  it('Должен получить информацию о пользователе', () => {
    const userId = testData[environment].userId;
    cy.request(`${Cypress.env('apiUrl')}/users/${userId}`)
      .its('status')
      .should('eq', 200);
  });
});

Такой подход минимизирует вероятность конфликтов с реальными данными и делает тесты более безопасными для production-среды.


Практические рекомендации

  • Хранить все чувствительные данные и URL в переменных окружения, избегая хардкода.
  • Использовать разные .env файлы для разных сред.
  • Настраивать таймауты и стратегии повторов под конкретную среду.
  • Разделять тестовые данные, чтобы они соответствовали особенностям каждого окружения.
  • Динамически менять конфигурацию через Cypress.config() и Cypress.env() при необходимости.

Эти методы обеспечивают масштабируемость и гибкость тестового покрытия, позволяя использовать единый набор тестов для локальной разработки, staging и production без дублирования кода.