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 для записи логов выполнения.