Setup and Teardown
Часто при написании тестов вам нужно проделать некоторую работу до того, как запустится тест, и некоторую работу по его завершению. 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
and afterEach
могут работать с асинхронным кодом также, как это делают асинхронные тесты - они могут либо принимать функцию done
в качестве параметра, либо возвращать promise. К примеру, if initializeCityDatabase()
возвращает promise, который вызывает resolve, когда база данных инициализирована, нам бы хотелось вернуть этот promise:
beforeEach(() => { return initializeCityDatabase(); });
Единовременная настройка #
В некоторых случаях, подготовительные работы нужны единожды в начале файла. Это может быть особенно неудобно, когда подготовительный код асинхронный и его нельзя просто заинлайнить. Jest предоставляет функции beforeAll
и afterAll
на этот случай.
К примеру, если и initializeCityDatabase
и clearCityDatabase
каждый вернули promise, а база данных городов должна быть переиспользована между тестами, можно было бы изменить код так:
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
блока, блоки before
и after
применяются только для тестов внутри этого блока 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 sausage', () => { expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true); }); test('San Juan <3 plantains', () => { expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true); }); });
Общие рекомендации #
Если ест падает, нужно проверить в первую очередь, что тест падает, будучи запущенным водиночку. В 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
для записи логов выполнения.