기능
- Vite의 설정, 변환기, 리졸버 및 플러그인 지원
- 앱과 동일한 설정으로 테스트 실행
- HMR과 유사한 스마트하고 즉각적인 watch 모드 제공
- Vue, React, Svelte, Lit, Marko 등을 위한 컴포넌트 테스트 지원
- TypeScript / JSX 즉시 사용 가능
- ESM 우선 지원, 최상위 await 지원
- Tinypool을 통한 워커 기반 멀티스레딩
- Tinybench를 통한 벤치마킹 지원
- 스위트 및 테스트 필터링, 타임아웃, 동시 실행 지원
- 프로젝트 지원
- Jest 호환 스냅샷
- 단언(assertion)을 위한 Chai 내장 및 Jest expect 호환 API 제공
- 모의(mocking)를 위한 Tinyspy 내장
- DOM 모의를 위한 happy-dom 또는 jsdom 지원
- 브라우저에서 컴포넌트 테스트를 실행하기 위한 브라우저 모드
- v8 또는 istanbul을 통한 코드 커버리지
- Rust와 유사한 인소스 테스트
- expect-type을 통한 타입 테스트
- 샤딩 지원
- 처리되지 않은 오류 보고
테스트, 개발 및 빌드 간 공유 구성
Vitest는 Vite의 설정, 변환기, 리졸버 및 플러그인을 활용하여 앱과 동일한 설정으로 테스트를 실행할 수 있도록 합니다.
자세한 내용은 Vitest 구성을 참조하세요.
Watch 모드
$ vitest
소스 코드나 테스트 파일을 수정하면 Vitest는 모듈 그래프를 스마트하게 검색하고 관련 테스트만 다시 실행합니다. 이는 Vite에서 HMR이 작동하는 방식과 유사합니다.
vitest
는 개발 환경에서 기본적으로 watch mode
로 시작하며, CI 환경(process.env.CI
가 존재할 때)에서는 run mode
로 스마트하게 시작합니다. vitest watch
또는 vitest run
을 사용하여 원하는 모드를 명시적으로 지정할 수 있습니다.
--standalone
플래그를 사용하여 Vitest를 시작하면 백그라운드에서 계속 실행됩니다. 이 모드에서는 변경 사항이 발생하기 전까지는 어떤 테스트도 실행하지 않습니다. 소스 코드가 변경되더라도 해당 소스를 가져오는 테스트가 실행될 때까지 Vitest는 테스트를 실행하지 않습니다.
즉시 사용 가능한 일반적인 웹 관용구
ES 모듈 / TypeScript / JSX / PostCSS를 즉시 사용할 수 있습니다.
스레드
기본적으로 Vitest는 Tinypool( Piscina의 경량 포크)을 통해 node:child_process
를 사용하여 여러 프로세스에서 테스트 파일을 실행하며, 이를 통해 테스트를 동시에 실행할 수 있습니다. 테스트 스위트 속도를 더욱 높이려면 node:worker_threads
를 사용하여 테스트를 실행하도록 --pool=threads
를 활성화하는 것을 고려하십시오(일부 패키지는 이 설정에서 작동하지 않을 수 있으니 주의하십시오).
단일 스레드 또는 프로세스에서 테스트를 실행하려면 poolOptions
를 참조하십시오.
Vitest는 또한 각 파일의 환경을 격리하여 한 파일의 환경 변형이 다른 파일에 영향을 미치지 않도록 합니다. 격리는 --no-isolate
를 CLI에 전달하여 비활성화할 수 있습니다(정확성을 희생하고 실행 성능을 향상시킬 수 있습니다).
테스트 필터링
Vitest는 테스트 실행 속도를 높여 개발에 집중할 수 있도록 테스트 범위를 좁히는 여러 가지 방법을 제공합니다.
테스트 필터링에 대해 자세히 알아보십시오.
테스트 동시 실행
연속적인 테스트에서 .concurrent
를 사용하여 병렬로 시작할 수 있습니다.
import { describe, it } from 'vitest';
// concurrent로 표시된 두 테스트는 병렬로 실행됩니다.
describe('suite', () => {
it('serial test', async () => {
/* ... */
});
it.concurrent('concurrent test 1', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 2', async ({ expect }) => {
/* ... */
});
});
스위트에서 .concurrent
를 사용하면 해당 스위트의 모든 테스트가 병렬로 시작됩니다.
import { describe, it } from 'vitest';
// 이 스위트 내의 모든 테스트는 병렬로 실행됩니다.
describe.concurrent('suite', () => {
it('concurrent test 1', async ({ expect }) => {
/* ... */
});
it('concurrent test 2', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 3', async ({ expect }) => {
/* ... */
});
});
동시 스위트 및 테스트와 함께 .skip
, .only
, .todo
를 사용할 수도 있습니다. API 참조에서 자세히 알아보십시오.
WARNING
동시 테스트를 실행할 때 스냅샷 및 어설션은 올바른 테스트를 감지하기 위해 로컬 테스트 컨텍스트에서 expect
를 사용해야 합니다.
스냅샷
Jest 호환 스냅샷을 지원합니다.
import { expect, it } from 'vitest';
it('renders correctly', () => {
const result = render();
expect(result).toMatchSnapshot();
});
스냅샷에서 자세히 알아보십시오.
Chai 및 Jest expect
호환성
Chai는 Jest expect
호환 API를 사용하여 단언(assertion)을 위해 내장되어 있습니다.
참고로, 타사 라이브러리를 사용하여 매처를 추가하는 경우, test.globals
를 true
로 설정하면 더 나은 호환성을 제공합니다.
모킹
Tinyspy는 vi
객체에서 jest
호환 API를 사용하여 모의(mocking)를 위해 내장되어 있습니다.
import { expect, vi } from 'vitest';
const fn = vi.fn();
fn('hello', 1);
expect(vi.isMockFunction(fn)).toBe(true);
expect(fn.mock.calls[0]).toEqual(['hello', 1]);
fn.mockImplementation((arg: string) => arg);
fn('world', 2);
expect(fn.mock.results[1].value).toBe('world');
Vitest는 DOM 및 브라우저 API 모의를 위해 happy-dom 또는 jsdom을 모두 지원합니다. Vitest와 함께 제공되지 않으므로 별도로 설치해야 합니다.
$ npm i -D happy-dom
$ npm i -D jsdom
그 후, 구성 파일에서 environment
옵션을 변경하세요.
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom', // 또는 'jsdom', 'node'
},
});
모킹에서 자세히 알아보십시오.
커버리지
Vitest는 v8
을 통한 네이티브 코드 커버리지와 istanbul
을 통한 계측된 코드 커버리지를 지원합니다.
{
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
}
커버리지에서 자세히 알아보십시오.
인소스 테스트
Vitest는 Rust의 모듈 테스트와 유사하게 구현과 함께 소스 코드 내에서 테스트를 실행할 수 있는 방법을 제공합니다.
이를 통해 테스트는 구현과 동일한 클로저 범위를 공유하고 노출하지 않고도 비공개 상태를 테스트할 수 있습니다. 동시에 개발을 위한 피드백 루프를 단축시킵니다.
// 구현
export function add(...args: number[]): number {
return args.reduce((a, b) => a + b, 0);
}
// 인소스 테스트 스위트
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('add', () => {
expect(add()).toBe(0);
expect(add(1)).toBe(1);
expect(add(1, 2, 3)).toBe(6);
});
}
인소스 테스트에서 자세히 알아보십시오.
벤치마킹 실험적
Tinybench를 통해 bench
함수를 사용하여 벤치마크 테스트를 실행하여 성능 결과를 비교할 수 있습니다.
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;
});
});
});
타입 테스트 실험적
타입 회귀를 잡기 위해 테스트를 작성할 수 있습니다. Vitest는 유사하고 이해하기 쉬운 API를 제공하기 위해 expect-type
패키지를 포함하여 제공됩니다.
import { assertType, expectTypeOf, test } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name is a string
assertType(mount({ name: 42 }));
});
샤딩
--shard
및 --reporter=blob
플래그를 사용하여 다른 머신에서 테스트를 실행할 수 있습니다. 모든 테스트 및 커버리지 결과는 --merge-reports
명령을 사용하여 CI 파이프라인의 마지막 단계에서 병합할 수 있습니다.
vitest --shard=1/2 --reporter=blob --coverage
vitest --shard=2/2 --reporter=blob --coverage
vitest --merge-reports --reporter=junit --coverage
자세한 내용은 성능 향상 | 샤딩
을 참조하십시오.
환경 변수
Vitest는 프런트엔드 관련 테스트와의 호환성을 유지하기 위해 .env
파일에서 VITE_
접두사가 붙은 환경 변수만 자동으로 로드하며, Vite의 확립된 규칙을 따릅니다. .env
파일에서 모든 환경 변수를 로드하려면 vite
에서 가져온 loadEnv
메서드를 사용할 수 있습니다.
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';
export default defineConfig(({ mode }) => ({
test: {
// mode는 존재하는 경우 ".env.{mode}" 파일을 선택하는 방법을 정의합니다.
env: loadEnv(mode, process.cwd(), ''),
},
}));
처리되지 않은 오류
기본적으로 Vitest는 모든 처리되지 않은 거부, 처리되지 않은 예외(Node.js에서) 및 오류 이벤트( 브라우저에서)를 포착하여 보고합니다.
이 동작은 수동으로 오류를 포착하여 비활성화할 수 있습니다. Vitest는 콜백이 사용자에 의해 처리되었다고 가정하고 오류를 보고하지 않습니다.
// Node.js에서
process.on('unhandledRejection', () => {
// 사용자 정의 핸들러
});
process.on('uncaughtException', () => {
// 사용자 정의 핸들러
});
// 브라우저에서
window.addEventListener('error', () => {
// 사용자 정의 핸들러
});
window.addEventListener('unhandledrejection', () => {
// 사용자 정의 핸들러
});
또는 dangerouslyIgnoreUnhandledErrors
옵션을 사용하여 보고된 오류를 무시할 수도 있습니다. Vitest는 여전히 오류를 보고하지만 테스트 결과에 영향을 미치지 않습니다(종료 코드는 변경되지 않음).
오류가 포착되지 않았음을 테스트해야 하는 경우 다음과 같은 테스트를 만들 수 있습니다.
test('my function throws uncaught error', async ({ onTestFinished }) => {
onTestFinished(() => {
// 테스트 중에 이벤트가 호출되지 않은 경우,
// 다음 테스트가 시작되기 전에 제거되었는지 확인합니다.
process.removeAllListeners('unhandledrejection');
});
return new Promise((resolve, reject) => {
process.once('unhandledrejection', error => {
try {
expect(error.message).toBe('my error');
resolve();
} catch (error) {
reject(error);
}
});
callMyFunctionThatRejectsError();
});
});