セットアップとティアダウン
テストを作成する際に、テスト実行前に必要なセットアップ作業と、テスト実行後に必要な終了作業があることがよくあります。 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` パラメータを受け取るか、Promise を返すことができます。たとえば、`initializeCityDatabase()` がデータベースの初期化時に解決される Promise を返す場合、その 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` ブロック内のテストにのみ適用されます。
たとえば、都市データベースだけでなく、食品データベースもあるとします。異なるテストに対して異なるセットアップを行うことができます
// 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` は、`describe` ブロック内の `beforeEach` の前に実行されることに注意してください。すべてのフックの実行順序を説明すると役立つ場合があります。
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 ハンドラを実行します。これは、`describe` ブロック内ではなく、`before*` と `after*` ハンドラ内でセットアップとティアダウンを行うもう 1 つの理由です。 `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 で 1 つのテストのみを実行するには、その `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` を試すこともできます。