Перейти до основного змісту
Версія: 25.x

Підготовка та очистка

Часто під час написання тестів є певна підотовча робота, яка повинна бути виконана перед запуском тестів а також певна фінальна робота, яка повинна бути виконана після запуску тестів. 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 застосовуються тільки до тестів в межах цього блоку.

Наприклад, уявімо, що у нас є не тільки база даних міст, але і база даних їжі. Ми могли б виконати різні налаштування для різних тестів:

// Застосовується до всіх тестів у поточному файлі
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', () => {
// Застосовується тільки до тестів в поточному блоці desribe
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

Порядок виконання блоків describe і test

Jest виконує всі обробники блоків describe у файлі з тестами перед тим, як виконати будь-який тест. Це ще одна причина налаштовувати тести та виконувати очистку всередині обробників before* і after*, а не всередині блоків describe. Після виконання всіх блоків describe, за замовчуванням, Jest послідовно запускає всі тести в тому порядку, в якому вони зустрічаються в коді, очікує на їх завершення та виконання очистки перед тим, як рухатися далі.

Розглянемо наступний тест файл та його вивід:

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

describe('describe inner 1', () => {
console.log('describe inner 1');
test('test 1', () => {
console.log('test for describe inner 1');
expect(true).toBe(true);
});
});

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

test('test 1', () => {
console.log('test for describe outer');
expect(true).toBe(true);
});

describe('describe inner 2', () => {
console.log('describe inner 2');
test('test for describe inner 2', () => {
console.log('test for describe inner 2');
expect(false).toBe(false);
});
});

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

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

Загальні поради

Якщо тест падає, одна з перших речей, яку варто перевірити - це чи падає цей тест, якщо запускається лише він. Щоб запустити тільки один тест з допомогою 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, в якому логуються дані.