Setup은 테스트를 실행하기 전에 테스트 환경을 만드는 작업입니다.
Teardown은 테스트가 실행된 이후 정리하는 작업입니다.
테스트 하기전에 Setup을 통해 작업 환경을 만들고 테스트가 끝나면 Teardown을 통해 테스트 이전 상태로 돌려놔 일관성을 유지하는 것입니다.
테스트를 하기전에 반복적으로 해야할 작업이 있다면 beforeEach와 afterEach를 이용하면 됩니다.
아래 예제는 테스트를 시작하기 전에 데이터베이스를 설정하고 테스트가 끝나면 데이터베이스를 정리합니다.
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 함수는 비동기 함수도 다룰 수 있습니다.
함수 내에서 promise를 반환해주면 됩니다.
beforeEach(() => {
return initializeCityDatabase();
});
테스트를 할 때 Setup과 Teardwon을 한 번만 실행해야 할 때가 있을 것입니다.
이때는 beforeAll과 afterAll을 이용하면 됩니다.
사용하는 방법은 beforeEach와 afterEach와 같습니다.
beforeAll, beforeEach, afterAll, afterEach는 스코프를 가질 수 있습니다.
전역적으로 적용하고 싶다면 그냥 사용하면 되고 특정 구역안에서만 적용되게 하고 싶다면 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);
});
});
afterAll과 afterEach그리고 beforeAll과 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('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
예제 하나 더 보겠습니다.
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
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');
});
또한 unit단위 테스트에는 문제가 없었는데 통합했을 때 자주 실패한다면 다른 테스트가 이 테스트에 영향을 미치고 있을 수도 있습니다.
이 문제는 beforeEach를 사용하여 공유 상태를 수정함으로써 해결할 수 있습니다.
확신이 없다면 데이터 로그로 기록하는 beforeEach를 시도하면 됩니다.