테스트 API 참조
다음 타입은 아래 타입 서명에 사용됩니다.
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;
interface TestOptions {
/**
* 실행 시간이 초과되면 테스트가 실패합니다.
*/
timeout?: number;
/**
* 실패 시 지정된 횟수만큼 테스트를 재시도합니다.
*
* @default 0
*/
retry?: number;
/**
* 매번 실패하더라도 동일한 테스트를 여러 번 반복합니다.
* "retry" 옵션이 활성화되어 있고 테스트가 실패하면, 각 반복 주기마다 모든 재시도를 수행합니다.
* 임의적인 실패를 디버깅하는 데 유용합니다.
*
* @default 0
*/
repeats?: number;
}테스트 함수가 Promise를 반환하면, 테스트 실행기는 비동기 검증을 위해 Promise가 완료될 때까지 기다립니다. Promise가 거부되면 테스트는 실패합니다.
TIP
Jest에서 TestFunction은 (done: DoneCallback) => void 타입일 수도 있습니다. 이 형식이 사용되면 done이 호출될 때까지 테스트가 완료되지 않습니다. async 함수를 사용하여 동일한 결과를 얻을 수 있습니다. 마이그레이션 가이드 Done Callback 섹션을 참조하세요.
대부분의 옵션은 점 구문과 객체 구문을 모두 지원하므로 선호하는 스타일을 사용할 수 있습니다.
import { test } from 'vitest';
test.skip('skipped test', () => {
// some logic that fails right now
});import { test } from 'vitest';
test('skipped test', { skip: true }, () => {
// some logic that fails right now
});test
- 별칭:
it
test는 관련된 테스트들의 집합을 정의합니다. 테스트 이름과 테스트할 검증 로직을 담고 있는 함수를 인자로 받습니다.
선택적으로, 테스트 종료 전에 대기할 시간(밀리초)을 지정하는 타임아웃을 설정할 수 있습니다. 기본값은 5초이며, testTimeout 설정을 통해 전역적으로 구성할 수 있습니다.
import { expect, test } from 'vitest';
test('should work as expected', () => {
expect(Math.sqrt(4)).toBe(2);
});test.extend
- 별칭:
it.extend
test.extend를 사용하여 사용자 정의 픽스처로 테스트 컨텍스트를 확장합니다. 이 함수는 새로운 test 함수를 반환하며, 반환된 test 함수 또한 확장 가능하므로 필요에 따라 픽스처를 추가하거나 기존 픽스처를 재정의할 수 있습니다. 자세한 내용은 테스트 컨텍스트 확장을 참조하세요.
import { expect, test } from 'vitest';
const todos = [];
const archive = [];
const myTest = test.extend({
todos: async ({ task }, use) => {
todos.push(1, 2, 3);
await use(todos);
todos.length = 0;
},
archive,
});
myTest('add item', ({ todos }) => {
expect(todos.length).toBe(3);
todos.push(4);
expect(todos.length).toBe(4);
});test.skip
- 별칭:
it.skip
특정 테스트를 실행하지 않으려면, 코드를 삭제하지 않고 실행을 건너뛰고 싶을 때 test.skip을 사용합니다.
import { assert, test } from 'vitest';
test.skip('skipped test', () => {
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});테스트 컨텍스트 내에서 skip을 동적으로 호출하여 테스트를 건너뛸 수도 있습니다.
import { assert, test } from 'vitest';
test('skipped test', context => {
context.skip();
// Test skipped, no error
assert.equal(Math.sqrt(4), 3);
});test.skipIf
- 별칭:
it.skipIf
때로는 서로 다른 환경에서 테스트를 여러 번 실행해야 할 수 있으며, 일부 테스트는 특정 환경에 따라 달라질 수 있습니다. 테스트 코드를 if 문으로 감싸는 대신, 조건이 참일 경우 test.skipIf를 사용하여 테스트를 건너뛸 수 있습니다.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.skipIf(isDev)('prod only test', () => {
// this test only runs in production
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
test.runIf
- 별칭:
it.runIf
test.skipIf의 반대 기능을 제공합니다.
import { assert, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
test.runIf(isDev)('dev only test', () => {
// this test only runs in development
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
test.only
- 별칭:
it.only
test.only를 사용하여 특정 테스트 묶음 내에서 지정된 테스트만 실행합니다. 이는 디버깅 시 유용합니다.
선택적으로, 테스트 종료 전에 대기할 시간(밀리초)을 지정하는 타임아웃을 설정할 수 있습니다. 기본값은 5초이며, testTimeout 설정을 통해 전역적으로 구성할 수 있습니다.
import { assert, test } from 'vitest';
test.only('test', () => {
// Only this test (and others marked with only) are run
assert.equal(Math.sqrt(4), 2);
});전체 테스트 스위트에서 다른 테스트를 모두 제외하고 특정 파일 내의 only 테스트만 실행하는 것이 유용한 경우가 있습니다.
이를 위해 해당 테스트가 포함된 특정 파일로 vitest를 실행합니다.
# vitest interesting.test.tstest.concurrent
- 별칭:
it.concurrent
test.concurrent는 연속적인 테스트를 병렬로 실행하도록 지정합니다. 테스트 이름, 테스트 로직을 포함하는 비동기 함수, 선택적인 타임아웃(밀리초)을 인자로 받습니다.
import { describe, test } from 'vitest';
// The two tests marked with concurrent will be run in parallel
describe('suite', () => {
test('serial test', async () => {
/* ... */
});
test.concurrent('concurrent test 1', async () => {
/* ... */
});
test.concurrent('concurrent test 2', async () => {
/* ... */
});
});test.skip, test.only 및 test.todo는 동시 테스트와 함께 사용할 수 있습니다. 다음의 모든 조합이 유효합니다.
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // or test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // or test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // or test.concurrent.todo(/* ... */)동시 테스트를 실행할 때 스냅샷 및 단언은 올바른 테스트가 감지되도록 로컬 테스트 컨텍스트의 expect를 사용해야 합니다.
test.concurrent('test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test.concurrent('test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
test.sequential
- 별칭:
it.sequential
test.sequential은 테스트를 순차적으로 실행하도록 표시합니다. 이는 describe.concurrent 내에서 또는 --sequence.concurrent 명령 옵션을 사용하여 테스트를 순서대로 실행하려는 경우에 유용합니다.
import { describe, test } from 'vitest';
// 구성 옵션 { sequence: { concurrent: true } } 사용 시
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
test.sequential('sequential test 1', async () => {
/* ... */
});
test.sequential('sequential test 2', async () => {
/* ... */
});
// 동시 스위트 내에서
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
test.sequential('sequential test 1', async () => {
/* ... */
});
test.sequential('sequential test 2', async () => {
/* ... */
});
});test.todo
- 별칭:
it.todo
test.todo를 사용하여 나중에 구현될 테스트를 위한 스텁(stub)을 생성합니다. 보고서에 해당 테스트 항목이 표시되므로 아직 구현해야 할 테스트 수를 파악할 수 있습니다.
// An entry will be shown in the report for this test
test.todo('unimplemented test');test.fails
- 별칭:
it.fails
test.fails는 테스트가 실패할 것으로 예상됨을 명시적으로 나타냅니다.
import { expect, test } from 'vitest';
function myAsyncFunc() {
return new Promise(resolve => resolve(1));
}
test.fails('fail test', async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
test.each
- 별칭:
it.each
TIP
test.each는 Jest 호환성을 위해 제공되지만, Vitest는 TestContext를 통합하는 추가 기능을 가진 test.for도 제공합니다.
여러 데이터 세트로 동일한 테스트를 반복 실행해야 하는 경우 test.each를 사용합니다. 테스트 함수 매개변수 순서대로 테스트 이름에 printf 포맷을 사용하여 매개변수를 삽입할 수 있습니다.
%s: 문자열%d: 숫자%i: 정수%f: 부동 소수점 값%j: json%o: 객체%#: 테스트 케이스의 인덱스%%: 단일 퍼센트 기호('%')
import { expect, test } from 'vitest';
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// this will return
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3객체를 인수로 사용하는 경우 $ 접두사를 사용하여 객체 속성에 접근할 수도 있습니다.
test.each([
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
])('add($a, $b) -> $expected', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});
// this will return
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3객체를 인수로 사용하는 경우 .을 사용하여 객체 속성에 접근할 수도 있습니다.
test.each`
a | b | expected
${{ val: 1 }} | ${'b'} | ${'1b'}
${{ val: 2 }} | ${'b'} | ${'2b'}
${{ val: 3 }} | ${'b'} | ${'3b'}
`('add($a.val, $b) -> $expected', ({ a, b, expected }) => {
expect(a.val + b).toBe(expected);
});
// this will return
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3bVitest 0.25.3부터 템플릿 리터럴 테이블을 사용할 수도 있습니다.
- 첫 번째 행은
|로 구분된 열 이름이어야 합니다. - 하나 이상의 후속 데이터 행은
${value}구문을 사용하여 템플릿 리터럴 표현식으로 제공됩니다.
import { expect, test } from 'vitest';
test.each`
a | b | expected
${1} | ${1} | ${2}
${'a'} | ${'b'} | ${'ab'}
${[]} | ${'b'} | ${'b'}
${{}} | ${'b'} | ${'[object Object]b'}
${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}
`('returns $expected when $a is added $b', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});TIP
Vitest는 chai format 메서드로 $values를 처리합니다. 값이 너무 잘리면 구성 파일에서 chaiConfig.truncateThreshold 값을 늘릴 수 있습니다.
WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
test.for
- 별칭:
it.for
TestContext를 제공하기 위한 test.each의 대안입니다.
test.each와의 차이점은 배열 사례가 인자로 제공되는 방식입니다. 템플릿 문자열 사용을 포함한 다른 비배열 사례는 정확히 동일하게 작동합니다.
// `each`는 배열 사례를 펼칩니다.
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
// `for`는 배열 사례를 펼치지 않습니다.
test.for([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => {
expect(a + b).toBe(expected);
});두 번째 인수는 TestContext이며, 예를 들어 동시 스냅샷을 위해 사용할 수 있습니다.
test.concurrent.for([
[1, 1],
[1, 2],
[2, 1],
])('add(%i, %i)', ([a, b], { expect }) => {
expect(a + b).matchSnapshot();
});bench
- 타입:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench는 성능 측정을 정의합니다. Vitest에서 벤치마크는 일련의 작업을 정의하는 함수를 의미합니다. Vitest는 이 함수를 여러 번 실행하여 다양한 성능 결과를 보여줍니다.
Vitest는 내부적으로 tinybench 라이브러리를 사용하며, 세 번째 인수로 사용할 수 있는 모든 옵션을 상속합니다.
import { bench } from 'vitest';
bench(
'normal sorting',
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);export interface Options {
/**
* 벤치마크 작업을 실행하는 데 필요한 시간(밀리초)
* @default 500
*/
time?: number;
/**
* 시간 옵션이 완료된 경우에도 작업이 실행되어야 하는 횟수
* @default 10
*/
iterations?: number;
/**
* 밀리초 단위로 현재 타임스탬프를 가져오는 함수
*/
now?: () => number;
/**
* 벤치마크를 중단하기 위한 AbortSignal
*/
signal?: AbortSignal;
/**
* 작업이 실패하면 throw합니다. (true인 경우 이벤트가 작동하지 않습니다.)
*/
throws?: boolean;
/**
* 준비 시간 (warm-up time, 밀리초)
* @default 100ms
*/
warmupTime?: number;
/**
* 준비 반복 횟수
* @default 5
*/
warmupIterations?: number;
/**
* 각 벤치마크 작업(주기) 전에 실행할 설정 함수
*/
setup?: Hook;
/**
* 각 벤치마크 작업(주기) 후에 실행할 정리 함수
*/
teardown?: Hook;
}테스트 케이스 실행 후 출력 구조 정보는 다음과 같습니다.
name hz min max mean p75 p99 p995 p999 rme samples
· normal sorting 6,526,368.12 0.0001 0.3638 0.0002 0.0002 0.0002 0.0002 0.0004 ±1.41% 652638export interface TaskResult {
/*
* 작업을 실행하는 동안 발생한 마지막 오류
*/
error?: unknown;
/**
* 벤치마크 작업(사이클)을 실행하는 데 걸린 시간(밀리초)
*/
totalTime: number;
/**
* 샘플의 최소값
*/
min: number;
/**
* 샘플의 최대값
*/
max: number;
/**
* 초당 작업 수
*/
hz: number;
/**
* 각 작업에 소요되는 시간(밀리초)
*/
period: number;
/**
* 각 작업 반복 시간의 작업 샘플(밀리초)
*/
samples: number[];
/**
* 샘플 평균/평균 (모평균의 추정값)
*/
mean: number;
/**
* 샘플 분산 (모분산의 추정값)
*/
variance: number;
/**
* 샘플 표준 편차 (모표준 편차의 추정값)
*/
sd: number;
/**
* 평균의 표준 오차 (표본 평균의 표본 분포의 표준 편차라고도 함)
*/
sem: number;
/**
* 자유도
*/
df: number;
/**
* 샘플의 임계값
*/
critical: number;
/**
* 오차 범위
*/
moe: number;
/**
* 상대 오차 범위
*/
rme: number;
/**
* 중앙값 절대 편차
*/
mad: number;
/**
* p50/중앙값 백분위수
*/
p50: number;
/**
* p75 백분위수
*/
p75: number;
/**
* p99 백분위수
*/
p99: number;
/**
* p995 백분위수
*/
p995: number;
/**
* p999 백분위수
*/
p999: number;
}bench.skip
- 타입:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench.skip 구문을 사용하여 특정 벤치마크의 실행을 건너뛸 수 있습니다.
import { bench } from 'vitest';
bench.skip('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.only
- 타입:
(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void
bench.only를 사용하여 주어진 테스트 묶음에서 특정 벤치마크만 실행합니다. 이는 디버깅 시 유용합니다.
import { bench } from 'vitest';
bench.only('normal sorting', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});bench.todo
- 타입:
(name: string | Function) => void
bench.todo는 나중에 구현할 벤치마크를 위한 자리 표시자(stub) 역할을 합니다.
import { bench } from 'vitest';
bench.todo('unimplemented test');describe
파일 최상위 레벨에서 test 또는 bench를 사용하면 해당 파일이 암묵적인 테스트 스위트의 일부로 간주됩니다. describe를 사용하면 현재 컨텍스트에서 관련된 테스트, 벤치마크 및 다른 중첩된 스위트들을 묶어 새로운 테스트 그룹을 정의할 수 있습니다. 테스트 그룹을 사용하면 테스트 및 벤치마크를 체계적으로 구성하여 보고서를 더 명확하게 만들 수 있습니다.
// basic.spec.ts
// 테스트 구성
import { describe, expect, test } from 'vitest';
const person = {
isActive: true,
age: 32,
};
describe('person', () => {
test('person is defined', () => {
expect(person).toBeDefined();
});
test('is active', () => {
expect(person.isActive).toBeTruthy();
});
test('age limit', () => {
expect(person.age).toBeLessThanOrEqual(32);
});
});// basic.bench.ts
// 벤치마크 구성
import { bench, describe } from 'vitest';
describe('sort', () => {
bench('normal', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('reverse', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});테스트 또는 벤치마크 계층 구조를 만들고 싶다면 describe 구문을 중첩하여 사용할 수 있습니다.
import { describe, expect, test } from 'vitest';
function numberToCurrency(value: number | string) {
if (typeof value !== 'number') {
throw new TypeError('Value must be a number');
}
return value
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
describe('numberToCurrency', () => {
describe('given an invalid number', () => {
test('composed of non-numbers to throw error', () => {
expect(() => numberToCurrency('abc')).toThrowError();
});
});
describe('given a valid number', () => {
test('returns the correct currency format', () => {
expect(numberToCurrency(10000)).toBe('10,000.00');
});
});
});describe.skip
- Alias:
suite.skip
특정 describe 구문의 실행을 건너뛰려면 해당 스위트 내에서 describe.skip을 사용합니다.
import { assert, describe, test } from 'vitest';
describe.skip('skipped suite', () => {
test('sqrt', () => {
// 스위트가 생략되었으므로 오류가 발생하지 않습니다.
assert.equal(Math.sqrt(4), 3);
});
});describe.skipIf
- Alias:
suite.skipIf
때로는 여러 환경에서 스위트를 반복적으로 실행해야 할 수 있으며, 일부 스위트는 특정 환경에 따라 달라질 수 있습니다. if 문으로 스위트를 감싸는 대신, 조건이 참일 경우 describe.skipIf를 사용하여 스위트 실행을 건너뛸 수 있습니다.
import { describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.skipIf(isDev)('prod only test', () => {
// 이 테스트는 프로덕션 환경에서만 실행됩니다.
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
describe.runIf
- 별칭:
suite.runIf
describe.skipIf의 반대입니다.
import { assert, describe, test } from 'vitest';
const isDev = process.env.NODE_ENV === 'development';
describe.runIf(isDev)('dev only test suite', () => {
// this test suite only runs in development
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
describe.only
- 타입:
(name: string | Function, fn: TestFunction, options?: number | TestOptions) => void
특정 스위트만 실행하려면 describe.only를 사용합니다.
import { assert, describe, test } from 'vitest';
// 이 스위트(및 only로 표시된 다른 스위트)만 실행됩니다.
describe.only('suite', () => {
test('sqrt', () => {
assert.equal(Math.sqrt(4), 3);
});
});
describe('other suite', () => {
// ... 생략됨
});전체 테스트 스위트의 결과를 복잡하게 만드는 다른 테스트를 제외하고 특정 파일 내에서 only로 지정된 테스트만 실행하는 것이 유용한 경우가 있습니다.
이를 위해 해당 테스트가 포함된 특정 파일을 지정하여 vitest를 실행합니다.
# vitest interesting.test.tsdescribe.concurrent
- Alias:
suite.concurrent
describe.concurrent 는 모든 내부 스위트와 테스트를 병렬로 실행합니다.
import { describe, test } from 'vitest';
// 이 스위트 내의 모든 스위트와 테스트는 병렬로 실행됩니다.
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
describe('concurrent suite 2', async () => {
test('concurrent test inner 1', async () => {
/* ... */
});
test('concurrent test inner 2', async () => {
/* ... */
});
});
test.concurrent('concurrent test 3', async () => {
/* ... */
});
});.skip, .only 및 .todo는 동시 스위트에서도 작동합니다. 다음의 모든 조합이 유효합니다.
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // 또는 describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // 또는 describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // 또는 describe.concurrent.todo(/* ... */)동시 테스트를 실행할 때 스냅샷 및 검증은 올바른 테스트가 감지되도록 로컬 테스트 컨텍스트에서 expect를 사용해야 합니다.
describe.concurrent('suite', () => {
test('concurrent test 1', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
test('concurrent test 2', async ({ expect }) => {
expect(foo).toMatchSnapshot();
});
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
describe.sequential
- Alias:
suite.sequential
스위트에서 describe.sequential은 해당 스위트 내의 모든 테스트를 순차적으로 실행하도록 지정합니다. 이는 describe.concurrent 블록 내에서 또는 --sequence.concurrent 명령 옵션을 사용하여 테스트를 순차적으로 실행하려는 경우에 유용합니다.
import { describe, test } from 'vitest';
describe.concurrent('suite', () => {
test('concurrent test 1', async () => {
/* ... */
});
test('concurrent test 2', async () => {
/* ... */
});
describe.sequential('', () => {
test('sequential test 1', async () => {
/* ... */
});
test('sequential test 2', async () => {
/* ... */
});
});
});describe.shuffle
- Alias:
suite.shuffle
Vitest는 CLI 플래그 --sequence.shuffle 또는 구성 옵션 sequence.shuffle을 통해 전체 테스트를 임의의 순서로 실행하는 기능을 제공합니다. 하지만 테스트 스위트의 일부만 임의 순서로 실행하고 싶다면 이 플래그를 사용할 수 있습니다.
import { describe, test } from 'vitest';
describe.shuffle('suite', () => {
test('random test 1', async () => {
/* ... */
});
test('random test 2', async () => {
/* ... */
});
test('random test 3', async () => {
/* ... */
});
});
// 순서는 구성의 sequence.seed 옵션에 따라 달라집니다(기본적으로 Date.now())..skip, .only 및 .todo는 임의 스위트에서도 작동합니다.
WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
describe.todo
- Alias:
suite.todo
나중에 구현할 스위트를 스텁(stub) 처리하려면 describe.todo를 사용합니다. 구현해야 할 테스트의 개수를 보고서에서 확인할 수 있도록 해당 항목이 표시됩니다.
// 이 스위트에 대한 항목이 보고서에 표시됩니다.
describe.todo('unimplemented suite');describe.each
- Alias:
suite.each
동일한 데이터 세트를 기반으로 여러 테스트를 수행해야 하는 경우 describe.each를 사용합니다.
import { describe, expect, test } from 'vitest';
describe.each([
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
])('describe object add($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);
});
});Vitest 0.25.3부터 템플릿 리터럴 테이블을 사용할 수도 있습니다.
- 첫 번째 행은
|로 구분된 열 이름이어야 합니다. ${value}구문을 사용하여 템플릿 리터럴 표현식으로 제공되는 하나 이상의 후속 데이터 행.
import { describe, expect, test } from 'vitest';
describe.each`
a | b | expected
${1} | ${1} | ${2}
${'a'} | ${'b'} | ${'ab'}
${[]} | ${'b'} | ${'b'}
${{}} | ${'b'} | ${'[object Object]b'}
${{ asd: 1 }} | ${'b'} | ${'[object Object]b'}
`('describe template string add($a, $b)', ({ a, b, expected }) => {
test(`returns ${expected}`, () => {
expect(a + b).toBe(expected);
});
});WARNING
Vitest를 타입 검사기로 사용하는 경우 이 구문을 사용할 수 없습니다.
설정 및 해체
이러한 함수를 사용하면 테스트 생명 주기에 연결하여 설정 및 해체 코드를 반복하는 것을 피할 수 있습니다. 최상위 레벨에서 사용되는 경우 파일에 적용되고, describe 구문 내부에 있는 경우 현재 스위트에 적용됩니다. Vitest를 타입 검사기로 실행하는 경우 이러한 훅은 호출되지 않습니다.
beforeEach
- 타입:
beforeEach(fn: () => Awaitable<void>, timeout?: number)
현재 컨텍스트에서 각 테스트가 실행되기 전에 호출될 콜백 함수를 등록합니다. 함수가 Promise 객체를 반환하면 Vitest는 테스트를 실행하기 전에 Promise 객체가 완료될 때까지 기다립니다.
선택적으로 종료하기 전에 대기할 시간(밀리초)을 정의하는 시간 초과를 전달할 수 있습니다. 기본값은 5초입니다.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// 각 테스트 실행 전에 모의 데이터를 초기화하고 필요한 테스트 데이터를 추가합니다.
await stopMocking();
await addUser({ name: 'John' });
});위 예제에서 beforeEach는 각 테스트마다 사용자를 추가합니다.
beforeEach는 선택적 정리 함수( afterEach와 동일)도 허용합니다.
import { beforeEach } from 'vitest';
beforeEach(async () => {
// 각 테스트 실행 전에 한 번 호출됩니다.
await prepareSomething();
// 정리 함수, 각 테스트 실행 후에 한 번 호출됩니다.
return async () => {
await resetSomething();
};
});afterEach
- 타입:
afterEach(fn: () => Awaitable<void>, timeout?: number)
현재 컨텍스트에서 각 테스트가 완료된 후 호출될 콜백 함수를 등록합니다. 함수가 Promise 객체를 반환하면 Vitest는 계속하기 전에 Promise 객체가 완료될 때까지 기다립니다.
선택적으로 종료하기 전에 대기할 시간을 지정하기 위해 시간 초과(밀리초)를 제공할 수 있습니다. 기본값은 5초입니다.
import { afterEach } from 'vitest';
afterEach(async () => {
await clearTestingData(); // 각 테스트 실행 후 테스트 데이터 지우기
});위 예제에서 afterEach는 각 테스트 실행 후에 테스트 데이터가 정리되도록 보장합니다.
TIP
Vitest 1.3.0에 onTestFinished 훅이 추가되었습니다. 테스트 실행 중에 이 훅을 호출하여 테스트가 완료된 후 상태를 정리할 수 있습니다.
beforeAll
- 타입:
beforeAll(fn: () => Awaitable<void>, timeout?: number)
현재 컨텍스트에서 모든 테스트 실행을 시작하기 전에 한 번 호출될 콜백 함수를 등록합니다. 함수가 Promise 객체를 반환하면 Vitest는 테스트를 실행하기 전에 Promise 객체가 완료될 때까지 기다립니다.
선택적으로 종료하기 전에 대기할 시간을 지정하기 위해 시간 초과(밀리초)를 제공할 수 있습니다. 기본값은 5초입니다.
import { beforeAll } from 'vitest';
beforeAll(async () => {
await startMocking(); // 모든 테스트 실행 전에 한 번 호출됩니다.
});위 예제에서 beforeAll은 모든 테스트를 실행하기 전에 필요한 모의 데이터가 설정되도록 합니다.
beforeAll은 선택적 정리 함수( afterAll과 동일)도 허용합니다.
import { beforeAll } from 'vitest';
beforeAll(async () => {
// 모든 테스트 실행 전에 한 번 호출됩니다.
await startMocking();
// 정리 함수, 모든 테스트 실행 후에 한 번 호출됩니다.
return async () => {
await stopMocking();
};
});afterAll
- 타입:
afterAll(fn: () => Awaitable<void>, timeout?: number)
현재 컨텍스트에서 모든 테스트가 실행된 후 한 번 호출될 콜백 함수를 등록합니다. 함수가 Promise 객체를 반환하면 Vitest는 계속하기 전에 Promise 객체가 완료될 때까지 기다립니다.
선택적으로 종료하기 전에 대기할 시간을 지정하기 위해 시간 초과(밀리초)를 제공할 수 있습니다. 기본값은 5초입니다.
import { afterAll } from 'vitest';
afterAll(async () => {
await stopMocking(); // 이 메서드는 모든 테스트가 실행된 후에 호출됩니다.
});위 예제에서 afterAll은 모든 테스트가 완료된 후 stopMocking 메서드가 실행되도록 보장합니다.
테스트 훅
Vitest는 테스트 실행 중에 호출하여 테스트 실행이 완료되었을 때 상태를 정리할 수 있는 몇 가지 훅을 제공합니다.
WARNING
이러한 훅은 테스트 본문 외부에서 호출되면 오류를 발생시킵니다.
onTestFinished
이 훅은 테스트 실행이 완료된 후 항상 호출됩니다. 테스트 결과에 영향을 줄 수 있으므로 afterEach 훅 다음에 호출됩니다. 현재 테스트 결과가 담긴 TaskResult 객체를 받습니다.
import { onTestFinished, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});WARNING
테스트를 동시에 실행하는 경우 Vitest는 글로벌 훅에서 동시 테스트를 추적하지 않으므로 항상 테스트 컨텍스트에서 onTestFinished 훅을 사용해야 합니다.
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFinished }) => {
const db = connectDb();
onTestFinished(() => db.close());
db.query('SELECT * FROM users');
});이 훅은 재사용 가능한 로직을 만들 때 특히 유용합니다.
// 별도의 파일에 있을 수 있습니다.
function getTestDb() {
const db = connectMockedDb();
onTestFinished(() => db.close());
return db;
}
test('performs a user query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from users').perform()).toEqual([]);
});
test('performs an organization query', async () => {
const db = getTestDb();
expect(await db.query('SELECT * from organizations').perform()).toEqual([]);
});TIP
이 훅은 항상 역순으로 호출되며 sequence.hooks 옵션의 영향을 받지 않습니다.
onTestFailed
이 훅은 테스트가 실패한 후에만 호출됩니다. 테스트 결과에 영향을 줄 수 있으므로 afterEach 훅 다음에 호출됩니다. 현재 테스트 결과가 담긴 TaskResult 객체를 받습니다. 이 훅은 디버깅에 유용합니다.
import { onTestFailed, test } from 'vitest';
test('performs a query', () => {
const db = connectDb();
onTestFailed(e => {
console.log(e.result.errors);
});
db.query('SELECT * FROM users');
});WARNING
테스트를 동시에 실행하는 경우 Vitest는 글로벌 훅에서 동시 테스트를 추적하지 않으므로 항상 테스트 컨텍스트에서 onTestFailed 훅을 사용해야 합니다.
import { test } from 'vitest';
test.concurrent('performs a query', ({ onTestFailed }) => {
const db = connectDb();
onTestFailed(result => {
console.log(result.errors);
});
db.query('SELECT * FROM users');
});