В чем разница между хуками BeforeAll и BeforeEach в тестировании?

Ответ

BeforeAll (или beforeAll, @BeforeAll) и BeforeEach (или beforeEach, @BeforeEach) — это хуки настройки в тестовых фреймворках, которые выполняются в разные моменты жизненного цикла тестового набора (test suite).

BeforeAll

  • Выполняется: Один раз перед запуском всех тестов в данном тестовом классе или файле.
  • Область видимости: Общее состояние, созданное здесь, доступно для всех тестов и сохраняется между ними.
  • Типичное использование:
    • Установка дорогостоящих соединений (БД, внешние API).
    • Загрузка общих конфигурационных данных.
    • Инициализация глобальных ресурсов (например, тестового сервера).

BeforeEach

  • Выполняется: Перед каждым отдельным тестовым случаем (@Test).
  • Область видимости: Состояние должно быть изолированным для каждого теста.
  • Типичное использование:
    • Сброс или очистка состояния (например, очистка таблиц БД).
    • Создание свежего экземпляра тестируемого объекта.
    • Настройка моков (mocks) или заглушек (stubs) для каждого теста.

Пример на Jest (JavaScript/TypeScript):

describe('User Service', () => {
  let dbConnection;

  // Выполнится 1 РАЗ для всех тестов ниже
  beforeAll(async () => {
    dbConnection = await connectToDatabase(); // Дорогая операция
    console.log('Database connected');
  });

  // Выполнится перед КАЖДЫМ тестом
  beforeEach(() => {
    console.log('Preparing fresh test state...');
    // Очищаем таблицу пользователей перед каждым тестом
    dbConnection.query('DELETE FROM users');
  });

  test('should create a user', () => {
    // Здесь чистая БД
  });

  test('should find a user', () => {
    // И здесь тоже чистая БД
  });

  afterAll(() => {
    dbConnection.close();
  });
});

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

Ответ 18+ 🔞

А, слушай, вот эта тема с хуками в тестах — она же постоянно всех пиздюлей накрывает, пока не разберёшься! Ёпта, сейчас объясню на пальцах, без этой вашей заумной документации.

Представь себе, что ты на кухне готовишь. У тебя есть BeforeAll — это как один раз, блядь, достать с верхней полки тяжёлую сковородку, поставить её на плиту и включить огонь. Операция долгая, муторная, делать её перед каждым яичком — это же пиздец, да? Один раз сделал — и она греется, готова к работе для всех блинов и яиц.

А BeforeEach — это вот перед каждым, сука, новым яйцом, которое ты жаришь, ты сковородку-то быстро протёр тряпкой, масла свежего капнул. Чтобы от прошлого яйца пригорелая хуйня не мешала. Изоляция, блядь! Каждое яйцо должно жариться на чистой сковороде, иначе они все в одну кашу слипутся, и ты не поймёшь, какое из них протухло.

Вот смотри на примере, тут всё чётко:

describe('User Service', () => {
  let dbConnection; // Это наша сковорода

  // beforeAll - ДОСТАЛИ СКОВОРОДУ ОДИН РАЗ. Подключились к базе.
  beforeAll(async () => {
    dbConnection = await connectToDatabase(); // Дорогая операция, ебать
    console.log('Database connected');
  });

  // beforeEach - ПРОТИРАЕМ СКОВОРОДУ ПЕРЕД КАЖДЫМ ЯЙЦОМ. Чистим таблицу.
  beforeEach(() => {
    console.log('Preparing fresh test state...');
    dbConnection.query('DELETE FROM users'); // Вжух, и чисто!
  });

  test('should create a user', () => {
    // Тестим на чистой базе
  });

  test('should find a user', () => {
    // И здесь база тоже чистая, потому что beforeEach отработал снова
  });

  afterAll(() => {
    dbConnection.close(); // Погасили огонь, помыли сковороду
  });
});

Короче, главное правило, чтобы не облажаться: Если ресурс тяжёлый и общий для всех (типа соединения с базой, поднятия тестового сервера) — это BeforeAll, ёпта. Сделал один раз и забыл. Если нужно каждый тест запускать в чистой песочнице, чтобы они друг другу не насрали в состояние — это BeforeEach, блядь. Чистка, сброс, подготовка свежего объекта.

Запомни это, и у тебя тесты перестанут вести себя как непредсказуемая манда с ушами, которая то падает, то работает. Всё просто, как три копейки!