Sharing data между тестами

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


Использование Cypress.env для глобальных переменных

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

// Установка значения
Cypress.env('userId', 12345);

// Получение значения в другом тесте
const userId = Cypress.env('userId');

Особенности использования:

  • Значения, установленные через Cypress.env, сохраняются только на время выполнения теста, после перезапуска они не сохраняются.
  • Подходит для простых скалярных данных (строки, числа, булевы значения) и небольших объектов.
  • Не рекомендуется использовать для больших структур данных, так как это может снизить читаемость тестов.

Хранение данных в контексте тестов с cy.wrap и alias

Cypress позволяет привязывать данные к конкретной цепочке команд с помощью alias. Это эффективный способ передавать результаты асинхронных операций между тестами.

describe('Пользовательские сценарии', () => {
  before(() => {
    cy.request('POST', '/api/users', { name: 'Alice' })
      .its('body')
      .as('newUser'); // сохраняем тело ответа под alias
  });

  it('Использует данные нового пользователя', function() {
    cy.log(this.newUser.id);
  });
});

Ключевые моменты:

  • alias создаются с помощью .as('имя').
  • Доступ к alias возможен только через function() {} вместо стрелочных функций, потому что стрелочные функции не имеют собственного контекста this.
  • Такой подход идеально подходит для передачи данных, полученных в before или beforeEach.

Использование fixtures для статических и динамических данных

Файлы фикстур (fixtures) позволяют хранить заранее подготовленные данные в формате JSON и загружать их в тесты через cy.fixture().

// Пример fixtures/user.json
{
  "name": "Alice",
  "email": "alice@example.com"
}

// Использование в тесте
cy.fixture('user').then(user => {
  cy.request('POST', '/api/users', user).as('createdUser');
});

Преимущества:

  • Позволяет отделить данные от тестовой логики.
  • Удобно для тестирования с повторяющимися наборами данных.
  • Можно динамически модифицировать данные перед использованием в тесте.

Сохранение данных в localStorage или sessionStorage

Для сценариев, связанных с авторизацией или хранением пользовательских настроек в браузере, можно использовать веб-хранилища.

// Сохранение токена авторизации
cy.setLocalStorage('authToken', '123456789');

// Получение токена в другом тесте
const token = cy.getLocalStorage('authToken');

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

  • Данные сохраняются на время сессии браузера.
  • Удобно для имитации состояния авторизованного пользователя между тестами.
  • Не рекомендуется использовать для больших объёмов данных или структур, требующих частого обновления.

Применение внешних файлов и баз данных

Для комплексных сценариев иногда удобнее хранить промежуточные данные во внешних JSON-файлах или тестовых базах данных. Cypress позволяет взаимодействовать с файловой системой через cy.writeFile и cy.readFile.

// Сохранение данных
cy.writeFile('cypress/fixtures/tempUser.json', { id: 1, name: 'Alice' });

// Чтение данных в другом тесте
cy.readFile('cypress/fixtures/tempUser.json').then(user => {
  cy.log(user.name);
});

Плюсы и минусы:

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

Лучшие практики при обмене данными между тестами

  1. Минимизировать зависимость между тестами. Тесты должны оставаться максимально независимыми, чтобы при падении одного теста остальные оставались работоспособными.
  2. Использовать before или beforeEach для подготовки данных. Это повышает стабильность и читаемость тестов.
  3. Избегать глобальных переменных в браузере для больших структур данных. Лучше использовать fixtures или внешние файлы.
  4. Следить за асинхронностью. Любые данные, полученные через cy.request или cy.fixture, должны использовать цепочки команд Cypress или then.
  5. Очищать данные после тестов. Особенно актуально при работе с базой данных или API, чтобы тесты не зависели от состояния, оставленного предыдущими запусками.

Итоговое сравнение способов

Метод Сценарий применения Плюсы Минусы
Cypress.env Глобальные простые данные Простота использования Временные данные, не для сложных структур
alias / this Передача данных между тестами внутри describe Безопасное использование в цепочке команд Требуется function()
fixtures Статические или повторяющиеся данные Отделение данных от тестов Мало гибкости для динамических данных
localStorage / sessionStorage Авторизация, пользовательские настройки Сохраняет данные в сессии Не для больших структур данных
Внешние файлы / базы данных Сложные или долговременные данные Возможность сохранять между запусками Требует управления файлами/БД

Использование правильного подхода к обмену данными между тестами повышает устойчивость тестов, улучшает поддерживаемость кода и делает сценарии более предсказуемыми.