Изоляция тестов

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


Независимость тестов

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

  • Перезагрузка контекста браузера перед каждым тестом. Cypress создает новый экземпляр страницы, что предотвращает влияние предыдущих тестов на текущий.
  • Очистка cookies и localStorage. После завершения теста Cypress удаляет все сохраненные данные, чтобы следующий тест стартовал с чистого состояния.

Поддержание независимости тестов снижает вероятность появления «фантомных» ошибок, когда один тест ломается из-за изменений, внесенных другим тестом.


Хуки для подготовки и очистки

Cypress предоставляет набор хуков для настройки окружения и очистки после тестов:

  • before(): выполняется один раз перед всеми тестами в блоке describe. Используется для глобальной настройки, такой как аутентификация или подготовка тестовых данных.
  • beforeEach(): выполняется перед каждым тестом. Обычно здесь выполняется сброс состояния приложения, переход на стартовую страницу или создание необходимых данных.
  • afterEach(): выполняется после каждого теста. Используется для очистки данных или логирования состояния после выполнения теста.
  • after(): выполняется один раз после всех тестов блока. Может использоваться для удаления тестовой среды или закрытия соединений.

Пример использования:

describe('Работа с формой регистрации', () => {
  before(() => {
    cy.visit('/login');
  });

  beforeEach(() => {
    cy.clearCookies();
    cy.clearLocalStorage();
  });

  it('Заполняет форму и отправляет данные', () => {
    cy.get('#username').type('testuser');
    cy.get('#password').type('password123');
    cy.get('form').submit();
    cy.contains('Добро пожаловать, testuser');
  });

  afterEach(() => {
    cy.reload();
  });
});

Разделение тестов на блоки

Использование describe и context позволяет логически разделять тесты и изолировать их по функционалу. Каждый блок создаёт собственную область видимости для хуков и тестов, что облегчает управление состоянием и повторное использование подготовленных данных.

describe('Профиль пользователя', () => {
  context('Редактирование данных', () => {
    beforeEach(() => {
      cy.login('user', 'password');
      cy.visit('/profile');
    });

    it('Изменяет имя пользователя', () => {
      cy.get('#name').clear().type('НовыйИмя');
      cy.get('form').submit();
      cy.contains('НовыйИмя');
    });
  });

  context('Смена пароля', () => {
    beforeEach(() => {
      cy.login('user', 'password');
      cy.visit('/change-password');
    });

    it('Обновляет пароль успешно', () => {
      cy.get('#oldPassword').type('password');
      cy.get('#newPassword').type('newPassword123');
      cy.get('form').submit();
      cy.contains('Пароль обновлён');
    });
  });
});

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


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

Фикстуры (fixtures) и моковые ответы (cy.intercept) играют важную роль в изоляции:

  • Фикстуры позволяют хранить статические тестовые данные и подставлять их в тесты, исключая зависимость от реальной базы данных.
  • Моки и стабы API позволяют полностью контролировать ответы серверной части, что предотвращает ошибки, связанные с недоступностью сервиса или изменением данных на сервере.

Пример использования фикстуры:

beforeEach(() => {
  cy.fixture('user.json').as('userData');
});

it('Логин с использованием фикстуры', function() {
  cy.get('#username').type(this.userData.username);
  cy.get('#password').type(this.userData.password);
  cy.get('form').submit();
  cy.contains('Добро пожаловать');
});

Пример использования мока:

cy.intercept('POST', '/api/login', { statusCode: 200, body: { token: 'abc123' } });

Важность повторяемости тестов

Изоляция напрямую связана с повторяемостью. Тесты должны проходить одинаково независимо от порядка выполнения. Несоблюдение изоляции может приводить к:

  • Ложно-положительным результатам, когда тест проходит, но только потому что предыдущий тест подготовил нужные данные.
  • Ложно-отрицательным результатам, когда тест падает из-за остаточного состояния от предыдущих сценариев.

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


Практические рекомендации по изоляции

  • Не использовать глобальные переменные для хранения состояния между тестами.
  • Всегда очищать cookies, localStorage и sessionStorage перед тестом.
  • Применять фикстуры и моковые данные для всех внешних зависимостей.
  • Разделять тесты на логические блоки с помощью describe и context.
  • Минимизировать зависимости между тестами, делая каждый сценарий автономным.

Эти практики повышают надёжность тестового набора и упрощают поддержку, позволяя выявлять ошибки только в коде, а не в окружении тестирования.