Skip to content
Vitest 3
Main Navigation 가이드 & API구성브라우저 모드고급 API
3.2.0
2.1.9
1.6.1
0.34.6

한국어

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
Italiano
Polski
Türkçe
čeština
magyar

한국어

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
Italiano
Polski
Türkçe
čeština
magyar

외관

Sidebar Navigation

소개

Vitest를 선택하는 이유

시작하기

기능

Vitest 구성하기

API

테스트 API 참조

Mock 함수

Vi

expect

expectTypeOf

assert

assertType

가이드

명령줄 인터페이스

테스트 필터링

테스트 프로젝트

리포터

커버리지

스냅샷

모킹

병렬 처리

타입 검사

Vitest UI

소스 내 테스팅

테스트 컨텍스트

테스트 어노테이션

테스트 환경

매처 확장하기

IDE 통합

디버깅

일반적인 오류

마이그레이션 가이드

Vitest 3.0으로 마이그레이션

Jest에서 마이그레이션

성능

테스트 성능 프로파일링

성능 향상

브라우저 모드

고급 API

다른 테스트 러너와의 비교

이 페이지에서

테스트 API 참조 ​

아래 타입 시그니처에 사용되는 타입은 다음과 같습니다.

ts
type Awaitable<T> = T | PromiseLike<T>;
type TestFunction = () => Awaitable<void>;

interface TestOptions {
  /**
   * 테스트 실행 시간이 너무 길어질 경우 실패 처리됩니다.
   */
  timeout?: number;
  /**
   * 테스트가 실패하면 설정된 횟수만큼 재시도합니다.
   *
   * @default 0
   */
  retry?: number;
  /**
   * 매번 실패하더라도 동일한 테스트를 여러 번 반복 실행합니다.
   * "retry" 옵션이 설정되어 있고 테스트가 실패할 경우, 각 반복 주기마다 모든 재시도 횟수를 소진합니다.
   * 무작위 실패를 디버깅하는 데 유용합니다.
   *
   * @default 0
   */
  repeats?: number;
}

테스트 함수가 프로미스를 반환하면, Vitest 러너는 비동기 검증을 수집하기 위해 해당 프로미스가 해결될 때까지 기다립니다. 프로미스가 거부되면 테스트는 실패합니다.

TIP

Jest에서 TestFunction은 (done: DoneCallback) => void 타입일 수도 있습니다. 이러한 형태가 사용될 경우, done이 호출될 때까지 테스트가 완료되지 않습니다. async 함수를 사용하여 동일한 결과를 얻을 수 있습니다. 마이그레이션 가이드 Done Callback 섹션을 참조하세요.

함수에 속성을 체이닝하여 옵션을 정의할 수 있습니다.

ts
import { test } from 'vitest';

test.skip('skipped test', () => {
  // 현재 실패하는 일부 로직
});

test.concurrent.skip('skipped concurrent test', () => {
  // 현재 실패하는 일부 로직
});

하지만 두 번째 인수로 객체를 제공할 수도 있습니다.

ts
import { test } from 'vitest';

test('skipped test', { skip: true }, () => {
  // 현재 실패하는 일부 로직
});

test('skipped concurrent test', { skip: true, concurrent: true }, () => {
  // 현재 실패하는 일부 로직
});

두 방식 모두 동일하게 작동하며, 둘 중 어느 것을 사용할지는 순전히 스타일적인 선택입니다.

참고로, 마지막 인수로 타임아웃을 제공하는 경우 더 이상 옵션을 사용할 수 없습니다.

ts
import { test } from 'vitest';

// ✅ 작동합니다.
test.skip('heavy test', () => {
  // ...
}, 10_000);

// ❌ 작동하지 않습니다.
test(
  'heavy test',
  { skip: true },
  () => {
    // ...
  },
  10_000
);

그러나 객체 내부에 타임아웃을 제공할 수 있습니다.

ts
import { test } from 'vitest';

// ✅ 작동합니다.
test('heavy test', { skip: true, timeout: 10_000 }, () => {
  // ...
});

test ​

  • 별칭: it

test는 관련된 검증 집합을 정의합니다. 테스트 이름과 테스트할 검증 내용을 담고 있는 함수를 인자로 받습니다.

선택적으로, 테스트 종료까지 기다릴 시간을 지정하는 타임아웃(밀리초)을 제공할 수 있습니다. 기본값은 5초이며, testTimeout으로 전역적으로 구성할 수 있습니다.

ts
import { expect, test } from 'vitest';

test('should work as expected', () => {
  expect(Math.sqrt(4)).toBe(2);
});

test.extend ​

  • 별칭: it.extend

test.extend를 사용하여 사용자 정의 픽스처로 테스트 컨텍스트를 확장합니다. 이는 새로운 test를 반환하며, 확장 가능하므로 필요에 따라 더 많은 픽스처를 구성하거나 기존 픽스처를 재정의할 수 있습니다. 자세한 내용은 테스트 컨텍스트 확장을 참조하세요.

ts
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을 사용하여 해당 테스트가 실행되지 않도록 할 수 있습니다.

ts
import { assert, test } from 'vitest';

test.skip('skipped test', () => {
  // 테스트 건너뜀, 오류 없음
  assert.equal(Math.sqrt(4), 3);
});

또한 컨텍스트의 skip 메서드를 동적으로 호출하여 테스트를 건너뛸 수 있습니다.

ts
import { assert, test } from 'vitest';

test('skipped test', context => {
  context.skip();
  // 테스트 건너뜀, 오류 없음
  assert.equal(Math.sqrt(4), 3);
});

Vitest 3.1부터는 조건을 알 수 없는 경우 skip 메서드의 첫 번째 인수로 해당 조건을 제공할 수 있습니다.

ts
import { assert, test } from 'vitest';

test('skipped test', context => {
  context.skip(Math.random() < 0.5, 'optional message');
  // 테스트 건너뜀, 오류 없음
  assert.equal(Math.sqrt(4), 3);
});

test.skipIf ​

  • 별칭: it.skipIf

어떤 경우에는 여러 환경에서 테스트를 여러 번 실행할 수 있으며, 일부 테스트는 환경에 따라 다를 수 있습니다. 테스트 코드를 if문으로 감싸는 대신 test.skipIf를 사용하여 조건이 참일 때마다 테스트를 건너뛸 수 있습니다.

ts
import { assert, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

test.skipIf(isDev)('prod only test', () => {
  // 이 테스트는 오직 프로덕션 환경에서만 실행됩니다.
});

WARNING

Vitest를 타입 체커로 사용하는 경우 이 구문을 사용할 수 없습니다.

test.runIf ​

  • 별칭: it.runIf

test.skipIf의 반대입니다.

ts
import { assert, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

test.runIf(isDev)('dev only test', () => {
  // 이 테스트는 개발 환경에서만 실행됩니다.
});

WARNING

Vitest를 타입 체커로 사용하는 경우 이 구문을 사용할 수 없습니다.

test.only ​

  • 별칭: it.only

test.only를 사용하여 주어진 스위트에서 특정 테스트만 실행합니다. 이것은 디버깅할 때 유용합니다.

선택적으로, 테스트 종료까지 기다릴 시간을 지정하는 타임아웃(밀리초)을 제공할 수 있습니다. 기본값은 5초이며, testTimeout으로 전역적으로 구성할 수 있습니다.

ts
import { assert, test } from 'vitest';

test.only('test', () => {
  // 이 테스트(및 only로 표시된 다른 테스트)만 실행됩니다.
  assert.equal(Math.sqrt(4), 2);
});

전체 테스트 스위트의 다른 모든 테스트를 무시하고 특정 파일에 있는 only 테스트를 실행하는 것이 매우 유용할 때가 있습니다. 이는 출력(결과)을 불필요하게 복잡하게 만들지 않습니다.

이를 위해 해당 테스트가 포함된 특정 파일로 vitest를 실행합니다.

# vitest interesting.test.ts

test.concurrent ​

  • 별칭: it.concurrent

test.concurrent는 연달아 정의된 테스트들을 병렬로 실행하도록 표시합니다. 테스트 이름, 실행할 테스트를 포함하는 비동기 함수, 그리고 선택적 타임아웃(밀리초)을 받습니다.

ts
import { describe, test } from 'vitest';

// concurrent로 표시된 두 테스트는 병렬로 실행됩니다.
describe('suite', () => {
  test('serial test', async () => {
    /* ... */
  });
  test.concurrent('concurrent test 1', async () => {
    /* ... */
  });
  test.concurrent('concurrent test 2', async () => {
    /* ... */
  });
});

test.skip, test.only, test.todo는 동시 테스트와 함께 작동합니다. 다음과 같은 모든 조합이 유효합니다.

ts
test.concurrent(/* ... */);
test.skip.concurrent(/* ... */); // 또는 test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // 또는 test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // 또는 test.concurrent.todo(/* ... */)

동시 테스트를 실행할 때, 스냅샷과 검증은 올바른 테스트를 감지하기 위해 로컬 테스트 컨텍스트에서 expect를 사용해야 합니다.

ts
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 명령 옵션과 함께 테스트를 순차적으로 실행하려는 경우에 유용합니다.

ts
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를 사용하여 나중에 구현할 테스트를 스텁합니다. 테스트 보고서에 해당 항목이 표시되므로, 구현해야 할 테스트가 몇 개인지 알 수 있습니다.

ts
// 이 테스트에 대한 항목이 보고서에 표시됩니다.
test.todo('unimplemented test');

test.fails ​

  • 별칭: it.fails

test.fails를 사용하여 특정 검증이 의도적으로 실패하도록 지정합니다.

ts
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: 객체
  • %#: 0부터 시작하는 테스트 케이스 인덱스
  • %$: 1부터 시작하는 테스트 케이스 인덱스
  • %%: 단일 퍼센트 기호 ('%')
ts
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);
});

// 결과는 다음과 같이 반환됩니다.
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3

$ 접두사를 사용하여 객체 속성 및 배열 요소에 접근할 수도 있습니다.

ts
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);
});

// 결과는 다음과 같이 반환됩니다.
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3

test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add($0, $1) -> $2', (a, b, expected) => {
  expect(a + b).toBe(expected);
});

// 결과는 다음과 같이 반환됩니다.
// ✓ add(1, 1) -> 2
// ✓ add(1, 2) -> 3
// ✓ add(2, 1) -> 3

인수로 객체를 사용하는 경우 .을 사용하여 객체 속성에 접근할 수도 있습니다.

ts
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);
});

// 결과는 다음과 같이 반환됩니다.
// ✓ add(1, b) -> 1b
// ✓ add(2, b) -> 2b
// ✓ add(3, b) -> 3b

Vitest 0.25.3부터 템플릿 리터럴 테이블도 사용할 수 있습니다.

  • 첫 번째 행은 |로 구분된 열 이름이어야 합니다.
  • 하나 이상의 후속 데이터 행은 ${value} 구문을 사용하여 템플릿 리터럴 표현식으로 제공되어야 합니다.
ts
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와의 차이점은 인수에 배열이 전달되는 방식에 있습니다. test.for에 전달되는 비배열 인수(템플릿 문자열 사용 포함)는 test.each와 정확히 동일하게 작동합니다.

ts
// `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이며, 예를 들어 동시 스냅샷에 사용할 수 있습니다.

ts
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 라이브러리를 사용하며, tinybench의 모든 옵션을 세 번째 인수로 사용할 수 있도록 상속합니다.

ts
import { bench } from 'vitest';

bench(
  'normal sorting',
  () => {
    const x = [1, 5, 4, 2, 3];
    x.sort((a, b) => {
      return a - b;
    });
  },
  { time: 1000 }
);
ts
export interface Options {
  /**
   * 벤치마크 작업을 실행하는 데 필요한 시간 (밀리초)
   * @default 500
   */
  time?: number;

  /**
   * 설정된 시간 옵션이 만료되었더라도 작업이 실행되어야 하는 횟수
   * @default 10
   */
  iterations?: number;

  /**
   * 현재 타임스탬프를 밀리초 단위로 가져오는 함수
   */
  now?: () => number;

  /**
   * 벤치마크를 중단하기 위한 AbortSignal
   */
  signal?: AbortSignal;

  /**
   * 작업이 실패하면 예외를 발생시킵니다 (이 값이 true이면 이벤트가 작동하지 않습니다).
   */
  throws?: boolean;

  /**
   * 준비 시간 (밀리초)
   * @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%   652638
ts
export interface TaskResult {
  /*
   * 작업을 실행하는 동안 발생한(던져진) 마지막 오류
   */
  error?: unknown;

  /**
   * 벤치마크 작업 (사이클)을 실행하는 데 걸린 시간 (밀리초)
   */
  totalTime: number;

  /**
   * 샘플의 최소값
   */
  min: number;
  /**
   * 샘플의 최대값
   */
  max: number;

  /**
   * 초당 작업 수
   */
  hz: number;

  /**
   * 각 작업에 걸리는 시간 (ms)
   */
  period: number;

  /**
   * 각 작업 반복에 소요된 시간(ms) 샘플
   */
  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 구문을 사용하여 특정 벤치마크 실행을 건너뛸 수 있습니다.

ts
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를 사용하여 주어진 스위트에서 특정 벤치마크만 실행합니다. 이것은 디버깅할 때 유용합니다.

ts
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를 사용하여 나중에 구현할 벤치마크를 스텁합니다.

ts
import { bench } from 'vitest';

bench.todo('unimplemented test');

describe ​

파일의 최상위 수준에서 test 또는 bench를 사용하면, 이들은 암시적 스위트의 일부로 자동 수집됩니다. describe를 사용하면 현재 컨텍스트에서 관련 테스트나 벤치마크, 그리고 다른 중첩된 스위트들을 묶어 새로운 스위트를 정의할 수 있습니다. 스위트를 사용하면 테스트와 벤치마크를 구성하여 보고서를 더 명확하게 만들 수 있습니다.

ts
// 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);
  });
});
ts
// 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 블록을 중첩할 수도 있습니다.

ts
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 ​

  • 별칭: suite.skip

스위트에서 describe.skip을 사용하여 특정 describe 블록이 실행되지 않도록 할 수 있습니다.

ts
import { assert, describe, test } from 'vitest';

describe.skip('skipped suite', () => {
  test('sqrt', () => {
    // 스위트 건너뜀, 오류 없음
    assert.equal(Math.sqrt(4), 3);
  });
});

describe.skipIf ​

  • 별칭: suite.skipIf

어떤 경우에는 여러 환경에서 스위트를 여러 번 실행할 수 있으며, 일부 스위트는 환경에 따라 다를 수 있습니다. 스위트를 if문으로 감싸는 대신 describe.skipIf를 사용하여 조건이 참일 때마다 스위트를 건너뛸 수 있습니다.

ts
import { describe, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

describe.skipIf(isDev)('prod only test suite', () => {
  // 이 테스트 스위트는 프로덕션에서만 실행됩니다.
});

WARNING

Vitest를 타입 체커로 사용하는 경우 이 구문을 사용할 수 없습니다.

describe.runIf ​

  • 별칭: suite.runIf

describe.skipIf의 반대입니다.

ts
import { assert, describe, test } from 'vitest';

const isDev = process.env.NODE_ENV === 'development';

describe.runIf(isDev)('dev only test suite', () => {
  // 이 테스트 스위트는 개발 환경에서만 실행됩니다.
});

WARNING

Vitest를 타입 체커로 사용하는 경우 이 구문을 사용할 수 없습니다.

describe.only ​

  • 타입: (name: string | Function, fn: TestFunction, options?: number | TestOptions) => void

describe.only를 사용하여 특정 스위트만 실행하도록 지정합니다.

ts
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.ts

describe.concurrent ​

  • 별칭: suite.concurrent

describe.concurrent는 모든 내부 스위트와 테스트를 병렬로 실행합니다.

ts
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는 동시 스위트와 함께 작동합니다. 다음과 같은 모든 조합이 유효합니다.

ts
describe.concurrent(/* ... */);
describe.skip.concurrent(/* ... */); // 또는 describe.concurrent.skip(/* ... */)
describe.only.concurrent(/* ... */); // 또는 describe.concurrent.only(/* ... */)
describe.todo.concurrent(/* ... */); // 또는 describe.concurrent.todo(/* ... */)

동시 테스트를 실행할 때, 스냅샷과 검증은 올바른 테스트를 감지하기 위해 로컬 테스트 컨텍스트에서 expect를 사용해야 합니다.

ts
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 ​

  • 별칭: suite.sequential

스위트 내의 describe.sequential은 모든 테스트를 순차적으로 실행하도록 표시합니다. 이것은 describe.concurrent 내에서 또는 --sequence.concurrent 명령 옵션과 함께 테스트를 순차적으로 실행하려는 경우에 유용합니다.

ts
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 ​

  • 별칭: suite.shuffle

Vitest는 CLI 플래그 --sequence.shuffle 또는 구성 옵션 sequence.shuffle을 통해 모든 테스트를 무작위 순서로 실행하는 방법을 제공합니다. 하지만 테스트 스위트의 일부만 무작위 순서로 테스트를 실행하고 싶다면, 이 플래그를 사용하여 해당 부분을 표시할 수 있습니다.

ts
import { describe, test } from 'vitest';

// 또는 describe('suite', { shuffle: true }, ...)
describe.shuffle('suite', () => {
  test('random test 1', async () => {
    /* ... */
  });
  test('random test 2', async () => {
    /* ... */
  });
  test('random test 3', async () => {
    /* ... */
  });

  // `shuffle`은 상속됩니다.
  describe('still random', () => {
    test('random 4.1', async () => {
      /* ... */
    });
    test('random 4.2', async () => {
      /* ... */
    });
  });

  // 내부에서 셔플 비활성화
  describe('not random', { shuffle: false }, () => {
    test('in order 5.1', async () => {
      /* ... */
    });
    test('in order 5.2', async () => {
      /* ... */
    });
  });
});
// 순서는 구성의 sequence.seed 옵션에 따라 달라집니다 (기본값은 Date.now()).

.skip, .only, .todo는 무작위 스위트와 함께 작동합니다.

WARNING

Vitest를 타입 체커로 사용하는 경우 이 구문을 사용할 수 없습니다.

describe.todo ​

  • 별칭: suite.todo

describe.todo를 사용하여 나중에 구현할 스위트를 스텁합니다. 테스트 보고서에 해당 항목이 표시되므로, 구현해야 할 테스트가 몇 개인지 알 수 있습니다.

ts
// 이 스위트에 대한 항목이 보고서에 표시됩니다.
describe.todo('unimplemented suite');

describe.each ​

  • 별칭: suite.each

TIP

describe.each는 Jest 호환성을 위해 제공되지만, Vitest는 인수 타입을 단순화하고 test.for와 정렬되는 describe.for도 제공합니다.

동일한 데이터에 의존하는 테스트가 두 개 이상인 경우 describe.each를 사용합니다.

ts
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} 구문을 사용하여 템플릿 리터럴 표현식으로 제공되어야 합니다.
ts
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.for ​

  • 별칭: suite.for

describe.each와의 차이점은 인수에 배열이 전달되는 방식에 있습니다. 다른 비배열 인수(템플릿 문자열 사용 포함)는 정확히 동일하게 작동합니다.

ts
// `each`는 배열 케이스를 펼칩니다.
describe.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => { 
  test('test', () => {
    expect(a + b).toBe(expected);
  });
});

// `for`는 배열 케이스를 펼치지 않습니다.
describe.for([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('add(%i, %i) -> %i', ([a, b, expected]) => { 
  test('test', () => {
    expect(a + b).toBe(expected);
  });
});

설정 및 해체 ​

이 함수를 사용하면 테스트의 수명 주기에 연결하여 설정 및 해체 코드를 반복하는 것을 피할 수 있습니다. 이 함수는 현재 컨텍스트에 적용됩니다. 예를 들어, 최상위 수준에서 사용되는 경우 파일에 적용되거나 describe 블록 내부에 있는 경우 현재 스위트에 적용됩니다. Vitest를 타입 체커로 실행할 때는 이러한 훅이 호출되지 않습니다.

beforeEach ​

  • 타입: beforeEach(fn: () => Awaitable<void>, timeout?: number)

현재 컨텍스트의 각 테스트가 실행되기 전에 호출될 콜백을 등록합니다. 함수가 프로미스를 반환하면, Vitest는 테스트를 실행하기 전에 해당 프로미스가 해결될 때까지 기다립니다.

선택적으로, 테스트 종료까지 기다릴 시간을 지정하는 타임아웃(밀리초)을 전달할 수 있습니다. 기본값은 5초입니다.

ts
import { beforeEach } from 'vitest';

beforeEach(async () => {
  // 각 테스트 실행 전에 모의를 지우고 일부 테스트 데이터를 추가합니다.
  await stopMocking();
  await addUser({ name: 'John' });
});

여기서 beforeEach는 각 테스트 실행 전에 사용자가 추가되도록 보장합니다.

beforeEach는 선택적 정리 함수( afterEach와 동일한 역할)도 허용합니다.

ts
import { beforeEach } from 'vitest';

beforeEach(async () => {
  // 각 테스트 실행 전에 한 번 호출됩니다.
  await prepareSomething();

  // 정리 함수, 각 테스트 실행 후에 한 번 호출됩니다.
  return async () => {
    await resetSomething();
  };
});

afterEach ​

  • 타입: afterEach(fn: () => Awaitable<void>, timeout?: number)

현재 컨텍스트의 각 테스트가 완료된 후 호출될 콜백을 등록합니다. 함수가 프로미스를 반환하면, Vitest는 계속 진행하기 전에 해당 프로미스가 해결될 때까지 기다립니다.

선택적으로, 테스트 종료까지 기다릴 시간을 지정하는 타임아웃(밀리초)을 제공할 수 있습니다. 기본값은 5초입니다.

ts
import { afterEach } from 'vitest';

afterEach(async () => {
  await clearTestingData(); // 각 테스트 실행 후 테스트 데이터를 지웁니다.
});

여기서 afterEach는 각 테스트 실행 후 테스트 데이터가 지워지도록 보장합니다.

TIP

Vitest 1.3.0부터 onTestFinished 훅이 추가되었습니다. 이 훅은 테스트 실행 중에 호출하여 테스트가 완료된 후 모든 상태를 정리할 수 있습니다.

beforeAll ​

  • 타입: beforeAll(fn: () => Awaitable<void>, timeout?: number)

현재 컨텍스트의 모든 테스트를 실행하기 전에 한 번 호출될 콜백을 등록합니다. 함수가 프로미스를 반환하면, Vitest는 테스트를 실행하기 전에 해당 프로미스가 해결될 때까지 기다립니다.

선택적으로, 테스트 종료까지 기다릴 시간을 지정하는 타임아웃(밀리초)을 제공할 수 있습니다. 기본값은 5초입니다.

ts
import { beforeAll } from 'vitest';

beforeAll(async () => {
  await startMocking(); // 모든 테스트 실행 전에 한 번 호출됩니다.
});

여기서 beforeAll은 테스트 실행 전에 모의 데이터가 설정되도록 보장합니다.

beforeAll은 선택적 정리 함수( afterAll과 동일한 역할)도 허용합니다.

ts
import { beforeAll } from 'vitest';

beforeAll(async () => {
  // 모든 테스트 실행 전에 한 번 호출됩니다.
  await startMocking();

  // 정리 함수, 모든 테스트 실행 후에 한 번 호출됩니다.
  return async () => {
    await stopMocking();
  };
});

afterAll ​

  • 타입: afterAll(fn: () => Awaitable<void>, timeout?: number)

현재 컨텍스트의 모든 테스트가 실행된 후 한 번 호출될 콜백을 등록합니다. 함수가 프로미스를 반환하면, Vitest는 계속 진행하기 전에 해당 프로미스가 해결될 때까지 기다립니다.

선택적으로, 테스트 종료까지 기다릴 시간을 지정하는 타임아웃(밀리초)을 제공할 수 있습니다. 기본값은 5초입니다.

ts
import { afterAll } from 'vitest';

afterAll(async () => {
  await stopMocking(); // 이 메서드는 모든 테스트 실행 후에 호출됩니다.
});

여기서 afterAll은 모든 테스트 실행 후 stopMocking 메서드가 호출되도록 보장합니다.

테스트 훅 ​

Vitest는 테스트 실행 _중_에 호출하여 테스트가 완료된 후 상태를 정리할 수 있는 몇 가지 훅을 제공합니다.

WARNING

이 훅은 테스트 본문 외부에서 호출되면 오류를 발생시킵니다.

onTestFinished ​

이 훅은 테스트가 완료된 후 항상 호출됩니다. afterEach 훅이 테스트 결과에 영향을 줄 수 있기 때문에, 이 훅은 afterEach 훅 다음에 호출됩니다. beforeEach 및 afterEach와 마찬가지로 ExtendedContext 객체를 받습니다.

ts
import { onTestFinished, test } from 'vitest';

test('performs a query', () => {
  const db = connectDb();
  onTestFinished(() => db.close());
  db.query('SELECT * FROM users');
});

WARNING

테스트를 동시에 실행하는 경우, Vitest는 전역 훅에서 동시 테스트를 추적하지 않으므로 항상 테스트 컨텍스트에서 onTestFinished 훅을 사용해야 합니다.

ts
import { test } from 'vitest';

test.concurrent('performs a query', ({ onTestFinished }) => {
  const db = connectDb();
  onTestFinished(() => db.close());
  db.query('SELECT * FROM users');
});

이 훅은 재사용 가능한 로직을 만들 때 특히 유용합니다.

ts
// 이 코드는 별도의 파일에 있을 수 있습니다.
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 훅이 테스트 결과에 영향을 줄 수 있기 때문에, 이 훅은 afterEach 훅 다음에 호출됩니다. beforeEach 및 afterEach와 마찬가지로 ExtendedContext 객체를 받습니다. 이 훅은 디버깅에 유용합니다.

ts
import { onTestFailed, test } from 'vitest';

test('performs a query', () => {
  const db = connectDb();
  onTestFailed(({ task }) => {
    console.log(task.result.errors);
  });
  db.query('SELECT * FROM users');
});

WARNING

테스트를 동시에 실행하는 경우, Vitest는 전역 훅에서 동시 테스트를 추적하지 않으므로 항상 테스트 컨텍스트에서 onTestFailed 훅을 사용해야 합니다.

ts
import { test } from 'vitest';

test.concurrent('performs a query', ({ onTestFailed }) => {
  const db = connectDb();
  onTestFailed(({ task }) => {
    console.log(task.result.errors);
  });
  db.query('SELECT * FROM users');
});
Pager
이전Vitest 구성하기
다음Mock 함수

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/api/

MIT 라이선스 하에 배포되었습니다.

Copyright (c) 2021-Present Vitest Team