Jest - Globals 기능 익히기 (2)

10 minute read

이번 포스트에서는 Jest 의 Globals 에 대해서 알아보겠습니다.

앞으로 Jest를 멋지게 사용하기 위해서는 다양한 기능들을 알아야 하겠지만 걱정하지 마세요. 단지 재미있는 소설책을 읽듯이 Jest의 다양한 기능들을 쉽게 익히실 수 있습니다.



Globals 기능?

Jest 는 테스트를 위한 methods와 objects를 글로벌 환경에 설정하기 때문에, 테스트를 위해 require 또는 import 를 사용하지 않아도됩니다. 그러나 명시적인 import 를 선호하는 경우 ‘import {describe, expect, it} from @jest/globals’ 를 사용해서 가져올 수 있습니다.

Methods

  • afterAll (fn, timeout)
  • afterEach (fn, timeout)
  • beforeAll (fn, timeout)
  • beforeEach (fn, timeout)
  • describe (name, fn)
  • describe.each (table)(name, fn, timeout)
  • describe.only (name, fn)
  • describe.only.each (table)(name, fn)
  • describe.skip (name, fn)
  • describe.skip.each (table)(name, fn)
  • test (name, fn, timeout)
  • test.each (tabel)(name, fn, timeout)
  • test.only (name, fn, timeout)
  • test.only.each (table)(name, fn)
  • test.skip (name, fn)
  • test.skip.each (table)(name, fn)
  • test.todo (name)


네! 그렇습니다. Globals 에 해당하는 매서드들은 많습니다. 하지만 두려워할 필요는 없습니다. 사용 가능한 메서드가 많아보이지만 크게 after, before, describe, test 4가지로 나눠서 생각하면 쉽습니다.

Methods Column 2
after, before 각각의 테스트를 진행하기 전과 또는, 테스트가 완료된 이후 시점에 사용자가 정의한 특정한 이벤트를 발생시킬 수 있습니다.
describe 유닛 테스트를 하나의 큰 그룹으로 정의하고 목적에 맞는 세부 테스트를 진행할때 사용합니다.
test 각각의 유닛 테스트에 필요한 가장 작은 단위의 테스트 단위입니다. 또한 4가지 메서드들은 메서드 체인을 통해 추가적인 기능을 수행할 수 있습니다.



그럼 Globals 메서드들의 종류와 사용방법에 대해 간단히 소개하도록 하겠습니다.



afterAll (fn, timeout)

  • 파일의 모든 테스트가 완료된 후 기능을 실행합니다.
  • 함수가 Promise 또는 Generator 를 반환하는 함수인 경우, Jest는 테스트를 계속 진행하기 전에 Promise가 해결될 때까지 기다립니다.
  • 선택적으로, 테스트 중단 전에 timeout을 제공할 수 있습니다. 기본 시간은 5초 입니다.
  • 테스트 전체에서 공유되는 일부 전역 설정 상태를 정리하는 경우에 유용합니다.
const globalDatabase = makeGlobalDatabase();
 
function cleanUpDatabase(db) {
    db.cleanUp();  
}
 
afterAll(() => {
    cleanUpDatabase(globalDatabase);
});
 
test('can find things', () => {
    return globalDatabase.find('thing', {}, results => {
        expect(result.length).toBeGreaterThan(0); // toBeGreaterThan(number); number 보다 크다
    });
});
 
test('can insert a thing', () => {
    return globalDatabase.insert('thing', makeThing(), response => {
        expect(response.success).toBeTruthy(); // toBeTruthy(); 는 true 의미
    });
});
  • 위 코드에서 afterAll은 모든 테스트가 실행된 후 cleanUpDatabase가 호출되도록 했습니다.
  • afterAll이 describe 블록안에 있으면 describe 블록의 끝에서 실행됩니다.
  • 모든 테스트 후가 아니라 각각의 테스트 후에 정리를 실행하려면 afterEach를 대신 사용해야 합니다.

afterEach (fn, timeout)

  • 파일의 각 테스트가 완료된 후 기능이 실행됩니다.
  • 함수가 Promise 또는 Generator를 반환하는 함수인 경우, Jest는 계속 진행하기 전에 promise가 해결될 때까지 기다립니다.
  • 선택적으로, 테스트 중단 timeout을 제공할 수 있습니다. 기본은 5초 입니다.
  • 각 테스트에서 생성된 임시 상태를 정리하려는 경우에 유용합니다.
const globalDatabase = makeGlobalDatabase();
function cleanUpDatabase(db) {
    db.cleanUp();
}
 
afterEach(() => {
    cleanUpDatabase(globalDatabase);
});
 
test('can find things', () => {
    return globalDatabase.find('thing', {}, results => {
        expect(results.length).toBeGreaterThan(0);
    });
});
 
test('can insert a thing', () => {
    return globalDatabase.insert('thing', makeThing(), response => {
        expect(response.success).toBeTruthy();
    });
});

위 코드에서 afterEach는 각 테스트가 실행된 후 cleanUpDatabase를 호출합니다. afterEach가 describe 블록안에 있으면 이 describe 블록의 끝에서 실행됩니다. 모든 테스트 후에 정리를 실행하려면 afterAll을 대신 사용하세요.

beforeAll (fn, timeout)

  • 파일의 테스트가 실행되기 전에 함수를 실행합니다.
  • 함수가 Promise 또는 Generator를 반환하는 함수인 경우, Jest는 계속 테스트를 진행하기 전에 promise가 해결될 때까지 기다립니다.
  • 선택적으로, 테스트 중단 전에 timeour을 제공할 수 있습니다. 기본은 5초 입니다.
  • 모든 테스트에서 사용될 전역 상태를 설정할때 유용합니다.
const globalDatabase = makeGlobalDatabase();
 
beforeAll(() => {
    // database 를 지우고 테스트를 위한 데이터를 추가합니다.
    // Jest는 테스트를 실행하기 전에 promise 가 해결 될 때까지 기다립니다.
    return globalDatabase.clear().then(() => {
        return globalDatabase.insert({testData: 'foo'});
    });
});
 
// 이 예제에서는 데이터베이스를 한번만 설정 했다는것에 주목하세요.
// 테스트 안에서 수정하지 않습니다.
test('can find things', () => {
    return globalDatabase.find('thing', {}, results => {
        expect(results.length).toBeGreaterThan(0);
    });
});
  • 위 코드에서 beforeAll은 테스트가 실행되기 전에 데이터베이스가 설정되도록 합니다.
  • 설정이 동기화 된 경우, beforeAll 없이 수행 할 수 있습니다.
  • Jest가 promise 가 해결되기를 기다릴 것이므로 비동기 설정도 할 수 있습니다.
  • beforeAll이 describe 블록 안에 있으면 이 describe 블록의 시작 부분에서 실행됩니다.
  • 테스트를 실행하기 전에 각각의 테스트 전에 무엇인가를 실행 하려면 beforeEach 를 사용하세요.

beforeEach (fn, timeout)

  • 파일의 각 테스트가 실행되기 전에 함수를 실행합니다.
  • 함수가 Promise 또는 generator 를 반환하는 함수인 경우, Jest는 계속 진행하기 전에 promise가 해결 될 때까지 기다립니다.
  • 선택적으로, 테스트 중단 전에 timeout 을 제공할 수 있습니다. 기본 timeout 시간은 5초 입니다.
  • 많은 테스트에서 사용될 일부 전역 상태를 재설정 하려는 경유 유용합니다.
const globalDatabase = makeGlobalDatabase();
 
beforeEach(() => {
    // database 를 지우고 테스트를 위한 데이터를 추가합니다.
    // Jest는 테스트를 실행하기 전에 promise 가 해결 될 때까지 기다립니다.
    return globalDatabase.clear().then(() => {
        return globalDatabase.insert({testData: 'foo'});
    });
});
 
test('can find things', () => {
    return globalDatabase.find('thing', {}, results => {
        expect(results.length).toBeGreaterThan(0);
    });
});
 
test('can insert a thing', () => {
    return globalDatabase.insert('thing', makeThing(), response => {
        expect(response.success).toBeTruthy();
    });
});
  • beforeEach는 각 테스트마다 데이터베이스가 재설정 되도록 합니다.
  • beforeEach가 describe 블록 안에 있으면 이 describe 블록의 각 테스트에 대해 실행됩니다.
  • 테스트를 실행하기 전에 기능을 한 번만 실행하려면 beforeAll 을 대신 사용하세요.

describe (name, fn)

  • describe (name, fn) 은 여러 관련 테스트를 그룹화하는 블록을 만듭니다.
  • 아래 예를 들어 맛은있지만 신맛이 없다는것을 다음과 같이 테스트 해볼 수 있습니다.
const myBeverage = {
    delicious: true,
    sour: false
};
 
describe('my beverage', () => {
    test('is delicious', () => {
        expect(myBeverage.delicious).toBeTruthy(); // toBeTruthy() 는 true 를 의미한다.
    });
 
    test('is not sour', () => {
        expect(myBeverage.sour).toBeFalsy(); // toBeFalsy() 는 false 를 의미한다.
    });
})
  • describe가 꼭 필요한것은 아닙니다. 최상위 레벨에서 직접 test 블록을 작성할 수 있습니다.
  • describe는 test를 그룹으로 구성하려는 경우에 유용합니다.

const binaryStringToNumber = binString => {
    if (!/^[01]+$/.test(binString)) {
        throw new CustomError('Not a binary number.');
    }
 
    return parseInt(binString, 2);
};
 
describe('binaryStringToNumber', () => {
    // invalid binary string
    describe('given an invalid binary string', () => {
        test('composed of non-number throws CustomError', () => {
            expect(() => binaryStringToNumber('abc')).toThrowError(CustomerError)
        });
 
        test('with extra whitespace throws CustomError', () => {
            expect(() => binaryStringToNumber('    100')).toThrowError(CustomerError);
        });
    });
    // valid binary string
    describe('given a valid binary string', () => {
        test('returns the correct number', () => {
            expect(binaryStringToNumber('100')).toBe(4);
        });
    });
});
  • test 계층 구조가 있는 경우, 위처럼 describe 블록을 중첩할 수도 있습니다.

describe.each (table) (name, fn, timeout)

  • 다른 데이터로 동일한 테스트 스위트(test suites)를 계속 복제하는 경우 describe.each를 사용하세요.
  • describe.each를 사용하면 테스트 스위트를 한 번 작성하고 데이터를 전달할 수 있습니다.

describe.each는 두 가지 API로 제공됩니다.

descirbe.each([
    [1, 1, 2],
    [1, 2, 3],
    [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
    test(`returns ${expected}`, () => {
        expect(a + b).toBe(expected)
    });
 
    test(`returned value not be greater than ${expected}`, () => {
        expect(a + b).not.toBeGreaterThan(expected); // not.toBeGreaterThan() ~보다 크지않다.
    });
 
    test(`returned value not be less than ${expected}`, () => {
        expect(a + b).not.toBeLessThan(expected); // not.toBeLessThan() ~보다 작지 않다.
    });
});
describe.each`
    a    | b    | expected
    ${1} | ${1} | ${2}
    ${1} | ${2} | ${3}
    ${2} | ${1} | ${3}
    `('$a + $b', ({a, b, expected}) => {
    test(`returns ${expected}`, () => {
        expect(a + b).toBe(expected);
    });
 
    test(`returned value not be greater than ${expected}`, () => {
        expect(a + b).not.toBeGreaterThan(expected);
    });
 
    test(`returned value not be less than ${expected}`, () => {
        expect(a + b).not.toBeLessThan(expected);
    });
});



describe.only (name, fn)

  • 하나의 describe 블록만 실행하려는 경우 describe.only 를 사용할 수 있습니다.
describe.only('my beberagel, () => {
    test('it delicious', () => {
        expect(myBeverage.delicious).toBeTruthy();
    });
    test('is not sour', () => {
        expect(myBeverage.sour).toBeFalsy();
    });
});
 
 
describe('my other beverage', () => {
    // ... 이 describe 는 skip 되어질 것입니다.
});



describe.only.each (table) (name, fn, timeout)

  • describe.each 와 동일하지만 하나의 describe 블록만 실행할 수 있습니다.
describe.only.each([
    [1, 1, 2],
    [1, 2, 3],
    [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
    test(`returns ${expected}`, () => {
        expect(a + b).toBe(expected);
    });
});
 
// 아래 test 는 실행되지 않습니다.
test('will not be ran', () => {
    expect(1 / 0).toBe(Infinity);
});
describe.only.each`
    a    | b    | expected
    ${1} | ${1} | ${2}
    ${1} | ${2} | ${3}
    ${2} | ${1} | ${3}
    `('returns $expected when $a is added $b', ({a, b, expected}) => {
    test('passes', () => {
        expect(a + b).toBe(expected);
    });
});
// 아래 test 는 실행되지 않습니다.
test('will not be ran', () => {
    expect(1 / 0).toBe(Infinity);
});



describe.skip (name, fn)

  • 특정 describe 블록을 실행하지 않으려면 describe.skip 을 사용할 수 있습니다.
describe('my beverage', () => {
    test('is delicious', () => {
        expect(myBeverage.delicious).toBeTruthy();
    });
 
    test('is not sour', () => {
        expect(myBeverage.sour).toBeFalsy();
    });
});
 
// describe.skip 으로 아래 기능은 skip 됩니다.
describe.skip('my other beverage', () => {
    // ... will be skipped
});



describe.skip.each (table) (name, fn, timeout)

  • describe.each 와 동일하지만 하나의 describe.skip.each 블록은 실행이 중지됩니다.
describe.skip.each([
    [1, 1, 2],
    [1, 2, 3],
    [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
    test(`returns ${expected}`, () => {
        expect(a + b).toBe(expected);
    });
});
 
// 아래 test 만 실행됩니다.
test('will be ran', () => {
    expect(1 / 0).toBe(Infinity);
});
describe.skip.each`
    a    | b    | expected
    ${1} | ${1} | ${2}
    ${1} | ${2} | ${3}
    ${2} | ${1} | ${3}
    `('returns $expected when $a is added $b', ({a, b, expected}) => {
    test('passes', () => {
        expect(a + b).toBe(expected);
    });
});
// 아래 test 만 실행됩니다.
test('will be ran', () => {
    expect(1 / 0).toBe(Infinity);
});



test (name, fn, timeout)

  • it (name, fn, timeout)
  • 테스트 파일에서 테스트를 실행하는 test 메서드만 있으면 됩니다.
  • 예를 들어, inchesOfRain() 함수가 0 이어야한다고 가정해 봅시다. 전체 테스트는 다음과 같습니다.
test ('did not rain', () => {
    expect(inchesOfRain()).toBe(0);
});
  • 첫 번째 인수는 테스트 이름입니다.
  • 두 번째 인수는 테스트할 기대치를 포함하는 함수입니다.
  • 세 번째 인수 (선택사항)은 테스트 중단 전에 대기 시간을 지정하기위한 timeout 입니다. (기본 5초)

[참고]
만약 promise 가 반환되면, Jest는 테스트가 완료되기 전에 promise 가 해결될 때까지 기다립니다. Jest는 일반적으로 done 이라는 테스트 함수를 인수로 제공하면 기다리게 됩니다. 이것은 콜백을 테스트 할 때 유용 할 수 있습니다. 여기에서 비동기 코드를 테스트하는 방법을 참조할 수 있습니다.

test('has lemon in it', () => {
    return fetchBeverageList().then(list => {
        expect(list).toContain('lemon'); // toContain(value) 은 value를 포함하는지 여부 확인
    })
});
  • 예를 들어, fetchBeverageList() 는 레몬이 포함된 목록으로 확인되는 promise 를 반환한다고 가정해 봅시다.
  • 테스트 요청이 즉시 반환 되더라도 promise 가 해결 될 때까지 테스트가 완료되지 않습니다.



test.each (table) (name, fn, timeout)

  • it.each(table)(name, fn), it.each `table`(name, fn)
  • 다른 데이터로 동일한 테스트를 계속 복제하는 경우 test.each를 사용하세요.
  • test.each를 사용하면 테스트를 한 번 작성하고 데이터를 전달할 수 있습니다.

test.each는 두 가지 API로 제공됩니다.

test.each([
    [1, 1, 2],
    [1, 2, 3],
    [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
    expect(a + b).toBe(expected);
});
test.each`
    a    | b    | expected
    ${1} | ${1} | ${2}
    ${1} | ${2} | ${3}
    ${2} | ${1} | ${3}
    `('returns $expected when $a is added $b', ({a, b, expected}) => {
    expect(a + b).toBe(expected);
});



test.only (name, fn, timeout)

  • it.only(name, fn, timeout), fit(name, fn, timeout)
  • 큰 테스트 파일을 디버깅 할 때는 종종 테스트 하위 집합만 실행해야할 경우가 있습니다.
  • test.only 를 사용하면 해당 테스트 파일에서 실행할 테스트만 지정할 수 있습니다.
test.only('it is raining', () => {
    expect(inchesOfRain()).toBeGreaterThan(0);
});
 
// 실행되지 않습니다.
test('it is not snowing', () => {
    expect(inchesOfSnow()).toBe(0);
});
  • test.only로 실행되기 때문에 ‘it is raining’ 테스트만 해당 테스트 파일에서 실행됩니다.
  • 일반적으로 유닛 테스트 소스에서 test.only를 사용하여 코드를 검사하지 않습니다. 디버깅 코드로 사용했다면 사용후 코드를 제거하세요.



test.only.each (table) (name, fn, timeout)

  • it.only.each(table)(name, fn), fit.each(table)(name, fn), it.only.each`table`(name, fn), fit.each`table`(name, fn)
  • 테스트 데이터로 특정 테스트만 실행하려면 test.only.each 를 사용합니다.
test.only.each([
    [1, 1, 2],
    [1, 2, 3],
    [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
  expect(a + b).toBe(expected);
});
// 실행되지 않습니다.
test('will not be ran', () => {
    expect(1 / 0).toBe(Infinity);
});
test.only.each`
    a    | b    | expected
    ${1} | ${1} | ${2}
    ${1} | ${2} | ${3}
    ${2} | ${1} | ${3}
`('returns $expected when $a is added $b', ({a, b, expected}) => {
    expect(a + b).toBe(expected);
});
 
// 실행되지 않습니다.
test('will not be ran', () => {
    expect(1 / 0).toBe(Infinity);
});



test.skip (name, fn)

  • it.skip(name, fn), xit(name, fn), xtest(name, fn)
  • 큰 코드베이스를 유지 관리하는 경우 때때로 어떤 이유로 일시적으로 중단된 테스트를 찾을 수 있습니다.
  • 테스트 코드를 삭제하지 않고 테스트 실행을 skip 하고 싶다면 test.skip 을 사용하여 skip 할 수 있습니다.
test('it is raining', () => {
    expect(inchesOfRain()).toBeGreaterThan(0);
});
 
// 이 테스트는 skip 합니다.
test.skip('it is not snowing', () => {
    expect(inchesOfSnow()).toBe(0);
});
  • 소스에서 테스트를 주석 처리 할 수도 있지만, 들여 쓰기와 구문 강조를 유지하기 위해 test.skip 을 사용하는 것이 더 좋습니다.



test.skip.each (table) (name, fn, timeout)

  • it.skip.each(table)(name, fn), xit.skip.each(table)(name, fn), xtest.skip.each(table)(name, fn),
  • it.skip.each`table`(name, fn), xit.each`table`(name, fn), xtest.each`table`(name, fn)
  • 테스트 데이터를 사용하는 구동 테스트 실행을 중지 하려는 경우 사용합니다.
test.skip.each([
    [1, 1, 2],
    [1, 2, 3],
    [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
    expect(a + b).toBe(expected); // will not be ran
});
 
test('will be ran', () => {
     expect(1 / 0).toBe(Infinity);
});
est.skip.each`
    a    | b    | expected
    ${1} | ${1} | ${2}
    ${1} | ${2} | ${3}
    ${2} | ${1} | ${3}
`('returns $expected when $a is added $b', ({a, b, expected}) => {
    expect(a + b).toBe(expected); // will not be ran
});
 
test('will be ran', () => {
    expect(1 / 0).toBe(Infinity);
});



test.todo (name)

  • it.todo(name)
  • 테스트 작성을 계획할 때는 test.todo를 사용하세요.
  • 이 테스트는 마지막에 요약 출력에서 강조 표시되므로 여전히 수행해야 할 테스트 수를 알 수 있습니다.

[참고]
테스트 콜백 함수를 제공하면 오류가 발생합니다. 실행하지 않으려면 test.skip 을 사용하세요.

const add = (a, b) => a + b;
 
test.todo('add should be associative');




다음 포스트에서는 Jest Expect 기능에 대해서 알아보도록 하겠습니다.

Tags:

Categories:

Updated:

 

 

Leave a comment