Динамическая генерация данных

Динамическая генерация данных — ключевой элемент автоматизированного тестирования, особенно при работе с веб-приложениями, где требуется создавать уникальные значения для форм, пользователей, заказов и других сущностей. Использование статических данных ограничивает гибкость тестов и может приводить к конфликтам при повторном запуске тестов. Cypress предоставляет возможности для эффективной генерации таких данных напрямую в тестах, интеграции с внешними библиотеками и использования их для создания сложных сценариев.


Основные подходы к генерации данных

  1. Встроенные возможности JavaScript

Для простых задач часто достаточно стандартных методов JavaScript. Например, генерация случайных чисел и строк:

const randomNumber = Math.floor(Math.random() * 1000);
const randomString = Math.random().toString(36).substring(2, 10);

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


  1. Использование внешних библиотек

Для более сложной генерации данных применяются специализированные библиотеки:

  • Faker.js / @faker-js/faker — создание реалистичных пользовательских данных: имена, адреса, телефоны, электронная почта.
  • Chance.js — генерация случайных чисел, строк, дат и булевых значений.
  • uuid — генерация уникальных идентификаторов, полезна для создания уникальных записей в базе данных или при работе с API.

Пример с использованием Faker.js:

import { faker } from '@faker-js/faker';

const userData = {
  firstName: faker.name.firstName(),
  lastName: faker.name.lastName(),
  email: faker.internet.email(),
  password: faker.internet.password(12)
};

cy.get('input[name="firstName"]').type(userData.firstName);
cy.get('input[name="lastName"]').type(userData.lastName);
cy.get('input[name="email"]').type(userData.email);
cy.get('input[name="password"]').type(userData.password);

Динамическая генерация в цепочках команд Cypress

Cypress позволяет интегрировать генерацию данных непосредственно в цепочки команд с использованием cy.wrap() и алиасов:

const randomEmail = `user_${Date.now()}@example.com`;

cy.wrap(randomEmail).as('emailAlias');

cy.get('@emailAlias').then(email => {
  cy.get('input[name="email"]').type(email);
});

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


Генерация сложных объектов

Для тестирования более сложных сценариев, например, заказа с товарами, можно комбинировать массивы и объекты:

const generateOrder = () => {
  const products = [];
  const productCount = Math.floor(Math.random() * 5) + 1;

  for (let i = 0; i < productCount; i++) {
    products.push({
      id: faker.datatype.uuid(),
      name: faker.commerce.productName(),
      price: faker.commerce.price()
    });
  }

  return {
    orderId: faker.datatype.uuid(),
    customerName: faker.name.fullName(),
    email: faker.internet.email(),
    products
  };
};

const order = generateOrder();
cy.log(JSON.stringify(order));

Такой подход позволяет создавать данные с произвольной вложенностью, что особенно важно при тестировании API и сложных форм.


Интеграция с фикстурами

Cypress поддерживает работу с фикстурами (fixtures) для хранения шаблонов данных. Динамическая генерация может использоваться вместе с фикстурами для модификации шаблонов перед отправкой:

cy.fixture('userTemplate.json').then(template => {
  const user = {
    ...template,
    email: `test_${Date.now()}@example.com`
  };
  cy.request('POST', '/api/users', user);
});

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


Совмещение генерации с параметризацией тестов

Динамические данные особенно полезны в параметризованных тестах, когда одна и та же логика проверяется на множестве вариантов:

const userScenarios = Array.from({ length: 5 }, () => ({
  email: `user_${Date.now()}_${Math.floor(Math.random()*1000)}@example.com`,
  password: faker.internet.password(10)
}));

userScenarios.forEach(user => {
  it(`Создание пользователя ${user.email}`, () => {
    cy.get('input[name="email"]').type(user.email);
    cy.get('input[name="password"]').type(user.password);
    cy.get('button[type="submit"]').click();
    cy.contains('Пользователь создан').should('be.visible');
  });
});

Каждый запуск создает уникальные данные, полностью исключая конфликты при повторном тестировании.


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

  • Использовать динамическую генерацию для всех уникальных значений, которые могут конфликтовать при повторном запуске тестов.
  • Сохранять структуру данных через фикстуры, а изменять только уникальные поля.
  • Генерацию сложных объектов инкапсулировать в функции или утилиты, чтобы код теста оставался читаемым.
  • Для больших наборов данных и нагрузочного тестирования комбинировать генерацию с циклами и массивами, избегая ручного повторения кода.
  • При тестировании API и баз данных создавать временные данные, которые автоматически удаляются после завершения теста.

Вывод

Динамическая генерация данных в Cypress обеспечивает гибкость и масштабируемость тестирования. Использование стандартных методов JavaScript, внешних библиотек и фикстур позволяет создавать уникальные и реалистичные сценарии, предотвращать конфликты данных и упрощать поддержку тестов. Такой подход критически важен для надежного автоматизированного тестирования веб-приложений с большим количеством форм и пользователей.