Spec-Zone.ru › Jest

Настройка и очистка

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

Повторяющаяся настройка

Если для многих тестов требуется повторять одни и те же действия, можно использовать хуки beforeEach и afterEach.

Например, предположим, что несколько тестов взаимодействуют с базой данных городов. Перед каждым из этих тестов нужно вызвать метод initializeCityDatabase(), а после каждого — метод clearCityDatabase(). Это можно сделать так:

beforeEach(() => {
  initializeCityDatabase();
});

afterEach(() => {
  clearCityDatabase();
});

test('city database has Vienna', () => {
  expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
  expect(isCity('San Juan')).toBeTruthy();
});

beforeEach и afterEach могут работать с асинхронным кодом так же, как тесты могут работать с асинхронным кодом: для этого они могут принимать параметр done или возвращать промис. Например, если бы initializeCityDatabase() возвращал промис, который разрешается после инициализации базы данных, нам следовало бы вернуть этот промис:

beforeEach(() => {
  return initializeCityDatabase();
});

Однократная настройка

В некоторых случаях настройку нужно выполнить всего один раз — в начале файла. Это может быть особенно неудобно, если настройка асинхронная и её нельзя выполнить прямо в коде. Для таких ситуаций в Jest предусмотрены хуки beforeAll и afterAll.

Например, если бы initializeCityDatabase() и clearCityDatabase() возвращали промисы, а базу данных городов можно было использовать повторно в разных тестах, мы могли бы изменить код тестов так:

beforeAll(() => {
  return initializeCityDatabase();
});

afterAll(() => {
  return clearCityDatabase();
});

test('city database has Vienna', () => {
  expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
  expect(isCity('San Juan')).toBeTruthy();
});

Область действия

Хуки верхнего уровня before* и after* применяются ко всем тестам в файле. Хуки, объявленные внутри блока describe, применяются только к тестам в этом блоке describe.

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

// Applies to all tests in this file
beforeEach(() => {
  return initializeCityDatabase();
});

test('city database has Vienna', () => {
  expect(isCity('Vienna')).toBeTruthy();
});

test('city database has San Juan', () => {
  expect(isCity('San Juan')).toBeTruthy();
});

describe('matching cities to foods', () => {
  // Applies only to tests in this describe block
  beforeEach(() => {
    return initializeFoodDatabase();
  });

  test('Vienna <3 veal', () => {
    expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
  });

  test('San Juan <3 plantains', () => {
    expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
  });
});

Обратите внимание: beforeEach верхнего уровня выполняется перед beforeEach внутри блока describe. Порядок выполнения всех хуков можно проиллюстрировать следующим образом.

beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));

test('', () => console.log('1 - test'));

describe('Scoped / Nested block', () => {
  beforeAll(() => console.log('2 - beforeAll'));
  afterAll(() => console.log('2 - afterAll'));
  beforeEach(() => console.log('2 - beforeEach'));
  afterEach(() => console.log('2 - afterEach'));

  test('', () => console.log('2 - test'));
});

// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll

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

Jest выполняет все обработчики describe в файле тестов до запуска самих тестов. Это ещё одна причина выполнять настройку и очистку в обработчиках before* и after*, а не внутри блоков describe. После выполнения блоков describe Jest по умолчанию запускает все тесты последовательно, в порядке их обнаружения на этапе сбора, дожидаясь завершения и очистки каждого теста, прежде чем перейти к следующему.

Рассмотрим следующий пример файла тестов и его вывода:

describe('describe outer', () => {
  console.log('describe outer-a');

  describe('describe inner 1', () => {
    console.log('describe inner 1');

    test('test 1', () => console.log('test 1'));
  });

  console.log('describe outer-b');

  test('test 2', () => console.log('test 2'));

  describe('describe inner 2', () => {
    console.log('describe inner 2');

    test('test 3', () => console.log('test 3'));
  });

  console.log('describe outer-c');
});

// describe outer-a
// describe inner 1
// describe outer-b
// describe inner 2
// describe outer-c
// test 1
// test 2
// test 3

Как и для блоков describe и test, Jest вызывает хуки before* и after* в порядке их объявления. Обратите внимание, что сначала вызываются хуки after* из внешней области. Например, вот как можно настроить и очистить ресурсы, которые зависят друг от друга:

beforeEach(() => console.log('connection setup'));
beforeEach(() => console.log('database setup'));

afterEach(() => console.log('database teardown'));
afterEach(() => console.log('connection teardown'));

test('test 1', () => console.log('test 1'));

describe('extra', () => {
  beforeEach(() => console.log('extra database setup'));
  afterEach(() => console.log('extra database teardown'));

  test('test 2', () => console.log('test 2'));
});

// connection setup
// database setup
// test 1
// database teardown
// connection teardown

// connection setup
// database setup
// extra database setup
// test 2
// extra database teardown
// database teardown
// connection teardown
примечание

Если вы используете тестовый исполнитель jasmine2, учтите, что он вызывает хуки after* в обратном порядке относительно порядка их объявления. Чтобы получить идентичный вывод, приведённый выше пример следует изменить так:

  beforeEach(() => console.log('connection setup'));
+ afterEach(() => console.log('connection teardown'));

  beforeEach(() => console.log('database setup'));
+ afterEach(() => console.log('database teardown'));

- afterEach(() => console.log('database teardown'));
- afterEach(() => console.log('connection teardown'));

  // ...

Общие рекомендации

Если тест завершается с ошибкой, в первую очередь стоит проверить, возникает ли она, когда запускается только этот тест. Чтобы запустить в Jest только один тест, временно замените команду test на test.only:

test.only('this will be the only test that runs', () => {
  expect(true).toBe(false);
});

test('this test will not run', () => {
  expect('A').toBe('A');
});

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

© 2022 Facebook, Inc.
Licensed under the MIT License.
https://jestjs.io/docs/setup-teardown

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API