Хуки уровня теста

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

При вызове vest() создаётся контейнер тестового набора, внутри которого регистрируются проверки полей и групповые сценарии. Исполнение происходит последовательно:

  1. Инициализация состояния набора
  2. Выполнение подготовительных хуков
  3. Запуск тестов (проверок test)
  4. Выполнение завершающих хуков
  5. Сбор и возврат результата

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

Роль хуков уровня теста

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

Ключевые сценарии применения:

  • инициализация зависимостей перед выполнением проверок
  • сброс временного состояния между тестами
  • управление моками API и таймерами
  • логирование и трассировка выполнения
  • кэширование промежуточных вычислений

beforeEach

Хук beforeEach выполняется перед каждым тестом внутри набора.

Поведение:

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

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

Пример логической модели выполнения:

  • тест 1 → beforeEach → test → afterEach
  • тест 2 → beforeEach → test → afterEach

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

afterEach

Хук afterEach вызывается после завершения каждого теста.

Основные задачи:

  • очистка временных данных
  • сброс моков и заглушек
  • фиксация результатов выполнения
  • сбор диагностической информации

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

Особое значение имеет в сценариях асинхронной валидации, где необходимо гарантировать завершение побочных операций (например, сетевых запросов) до начала следующего теста.

beforeAll и afterAll

Для сценариев, где требуется единоразовая инициализация или завершение, применяются хуки уровня всего набора.

beforeAll

Выполняется один раз перед началом выполнения всех тестов.

Используется для:

  • создания соединений с внешними сервисами
  • загрузки конфигураций
  • инициализации глобальных моков
  • подготовки общих ресурсов

afterAll

Выполняется один раз после завершения всех тестов.

Используется для:

  • закрытия соединений
  • освобождения ресурсов
  • финализации логов
  • очистки глобального состояния

Порядок выполнения хуков

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

  1. beforeAll
  2. beforeEach
  3. test
  4. afterEach
  5. повтор beforeEach → test → afterEach
  6. afterAll

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

Контекст выполнения

Внутри хуков доступен общий контекст набора, который может включать:

  • текущие значения полей
  • промежуточные результаты проверок
  • состояние моков
  • пользовательские данные, добавленные через расширения

Мутации контекста в beforeEach распространяются на последующие тесты, однако изменения внутри afterEach не должны влиять на уже выполненные проверки.

Вложенные наборы и изоляция

Vest поддерживает структурирование тестов через вложенные блоки. В этом случае хуки работают с учётом области видимости:

  • хуки верхнего уровня применяются ко всем вложенным тестам
  • хуки вложенного блока действуют только внутри него
  • при конфликте приоритет имеет ближайший по уровню контекст

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

Асинхронные хуки

Хуки могут содержать асинхронную логику. Это важно при работе с:

  • API-запросами
  • загрузкой конфигураций
  • проверкой уникальности значений на сервере

Асинхронное выполнение требует строгого завершения перед переходом к следующему этапу жизненного цикла. Нарушение этого порядка приводит к гонкам состояний и некорректным результатам валидации.

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

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

  • в beforeEach создаются или обновляются зависимости
  • в тестах используются уже готовые сервисы
  • в afterEach происходит их очистка

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

Кэширование и оптимизация

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

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

Кэш обычно инициализируется в beforeEach или beforeAll и инвалидируется в afterEach.

Типовые ошибки при использовании хуков

Нарушение изоляции состояния:

  • перенос изменяемых объектов между тестами без клонирования
  • модификация глобальных переменных внутри beforeEach

Некорректная асинхронность:

  • отсутствие ожидания завершения операций в хуках
  • параллельное изменение состояния

Дублирование логики:

  • выполнение одинаковой инициализации в тестах вместо beforeEach
  • очистка ресурсов вручную внутри test вместо afterEach

Такие ошибки приводят к нестабильному поведению набора и усложняют отладку.

Влияние хуков на структуру валидации

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

  • сохранять тесты чистыми и декларативными
  • централизовать управление зависимостями
  • контролировать жизненный цикл данных
  • повышать воспроизводимость результатов

Модель жизненного цикла становится основой предсказуемого поведения всей системы валидации.