Управление тестовыми датасетами

Эффективное управление тестовыми данными является ключевым элементом при автоматизации тестирования с использованием WebdriverIO. Тестовые датасеты позволяют создавать масштабируемые, повторяемые и надежные тесты, минимизируя дублирование кода и повышая гибкость тестовых сценариев.

Хранение тестовых данных

Тестовые данные можно хранить в нескольких форматах:

  • JSON: универсальный и легко читаемый формат, подходящий для структурированных данных.
  • CSV: удобен для больших таблиц данных, часто используется при интеграции с внешними источниками.
  • JavaScript-модули: позволяют импортировать данные как объекты, что упрощает динамическую генерацию данных и использование констант.

Пример хранения данных в JSON:

[
  {
    "username": "user1",
    "password": "pass1"
  },
  {
    "username": "user2",
    "password": "pass2"
  }
]

Импорт данных в тест:

const users = require('../data/users.json');

describe('Тестирование авторизации', () => {
  users.forEach(user => {
    it(`Авторизация для ${user.username}`, async () => {
      await browser.url('/login');
      await $('#username').setValue(user.username);
      await $('#password').setValue(user.password);
      await $('#loginButton').click();
      await expect($('#welcomeMessage')).toHaveTextContaining('Добро пожаловать');
    });
  });
});

Параметризация тестов

WebdriverIO поддерживает параметризацию тестов через Data-Driven Testing, что позволяет запускать один и тот же тест с различными наборами данных.

const testData = [
  { username: 'user1', password: 'pass1', expected: 'Добро пожаловать' },
  { username: 'user2', password: 'pass2', expected: 'Добро пожаловать' }
];

describe('Авторизация с разными пользователями', () => {
  testData.forEach(({ username, password, expected }) => {
    it(`Проверка входа для ${username}`, async () => {
      await browser.url('/login');
      await $('#username').setValue(username);
      await $('#password').setValue(password);
      await $('#loginButton').click();
      await expect($('#welcomeMessage')).toHaveTextContaining(expected);
    });
  });
});

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

В некоторых сценариях требуется создавать уникальные данные на лету, например, для регистрации новых пользователей. Для этого можно использовать библиотеки типа Faker:

const { faker } = require('@faker-js/faker');

describe('Регистрация нового пользователя', () => {
  it('Создание нового пользователя с уникальными данными', async () => {
    const email = faker.internet.email();
    const password = faker.internet.password();

    await browser.url('/register');
    await $('#email').setValue(email);
    await $('#password').setValue(password);
    await $('#registerButton').click();
    await expect($('#successMessage')).toHaveTextContaining('Регистрация успешна');
  });
});

Разделение данных и логики теста

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

// data/users.js
module.exports = [
  { username: 'user1', password: 'pass1' },
  { username: 'user2', password: 'pass2' }
];
// tests/login.test.js
const users = require('../data/users');

describe('Авторизация пользователей', () => {
  users.forEach(user => {
    it(`Вход для ${user.username}`, async () => {
      await browser.url('/login');
      await $('#username').setValue(user.username);
      await $('#password').setValue(user.password);
      await $('#loginButton').click();
      await expect($('#welcomeMessage')).toHaveTextContaining('Добро пожаловать');
    });
  });
});

Использование фикстур и hooks

Для подготовки и очистки тестовых данных применяются hooks WebdriverIO, такие как before, beforeEach, afterEach, after.

describe('Тестирование с фикстурами', () => {
  let testUser;

  before(async () => {
    testUser = { username: 'tempUser', password: 'tempPass' };
    await createUserInDB(testUser); // функция создания пользователя в базе
  });

  after(async () => {
    await deleteUserFromDB(testUser); // функция удаления пользователя
  });

  it('Проверка входа созданного пользователя', async () => {
    await browser.url('/login');
    await $('#username').setValue(testUser.username);
    await $('#password').setValue(testUser.password);
    await $('#loginButton').click();
    await expect($('#welcomeMessage')).toHaveTextContaining('Добро пожаловать');
  });
});

Использование hooks гарантирует, что данные будут корректно подготовлены до выполнения теста и очищены после него, что повышает стабильность и повторяемость тестов.

Организация больших датасетов

Для сложных проектов имеет смысл структурировать данные по доменам или функциональным областям:

  • data/users.json – тестовые пользователи
  • data/products.json – данные товаров
  • data/orders.json – тестовые заказы

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

Генерация комбинаций тестовых данных

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

const usernames = ['user1', 'user2'];
const passwords = ['pass1', 'pass2'];

usernames.forEach(username => {
  passwords.forEach(password => {
    it(`Вход с ${username} и ${password}`, async () => {
      await browser.url('/login');
      await $('#username').setValue(username);
      await $('#password').setValue(password);
      await $('#loginButton').click();
      await expect($('#welcomeMessage')).toHaveTextContaining('Добро пожаловать');
    });
  });
});

Это позволяет обнаружить неожиданные проблемы при сочетании различных параметров.

Итоговые рекомендации по работе с тестовыми датасетами

  • Всегда отделять данные от логики тестов.
  • Использовать параметризацию для повторяющихся сценариев.
  • Применять динамическую генерацию данных при необходимости уникальности.
  • Хранить данные в удобных и структурированных форматах (JSON, JS-модули).
  • Подготавливать и очищать данные с помощью hooks для стабильности тестов.
  • Организовывать большие наборы данных по функциональным областям.
  • Использовать комбинаторное тестирование для покрытия максимального числа сценариев.

Такой подход обеспечивает масштабируемость, надежность и гибкость автоматизированных тестов на WebdriverIO, позволяя легко адаптировать их к изменяющимся требованиям проекта.