마이그레이션 가이드
Vitest 2.0으로 마이그레이션
기본 풀은 forks
로 설정됩니다
Vitest 2.0은 더 나은 안정성을 위해 pool
의 기본 구성을 'forks'
로 변경합니다. 자세한 내용은 PR에서 확인할 수 있습니다.
pool
을 지정하지 않고 poolOptions
를 사용했다면 구성을 업데이트해야 할 수 있습니다.
export default defineConfig({
test: {
poolOptions: {
threads: {
singleThread: true,
},
forks: {
singleFork: true,
},
},
},
});
훅은 스택에서 실행됩니다
Vitest 2.0 이전에는 모든 훅이 병렬로 실행되었습니다. 2.0에서는 모든 훅이 직렬로 실행됩니다. 또한 afterAll
/afterEach
훅은 역순으로 실행됩니다.
훅의 병렬 실행으로 되돌리려면 sequence.hooks
를 'parallel'
로 변경하세요.
export default defineConfig({
test: {
sequence: {
hooks: 'parallel',
},
},
});
suite.concurrent
는 모든 테스트를 동시에 실행합니다
이전에는 스위트에서 concurrent
를 지정하면 동시 테스트가 스위트별로 그룹화되어 순차적으로 실행되었습니다. 이제 Jest의 동작을 따라 모든 테스트가 동시에 실행됩니다(maxConcurrency
제한에 따름).
V8 Coverage의 coverage.ignoreEmptyLines
가 기본적으로 활성화됩니다
coverage.ignoreEmptyLines
의 기본값이 이제 true
입니다. 이 중대한 변경 사항은 코드 커버리지 보고서에 영향을 줄 수 있으며, 일부 프로젝트에서는 커버리지 임계값 조정이 필요할 수 있습니다. 이 조정은 coverage.provider
가 'v8'
일 때의 기본 설정에만 영향을 미칩니다.
watchExclude
옵션 제거
Vitest는 Vite의 watcher를 사용합니다. 파일 또는 디렉터리를 server.watch.ignored
에 추가하여 제외하세요.
export default defineConfig({
server: {
watch: {
ignored: ['!node_modules/examplejs'],
},
},
});
--segfault-retry
제거됨
기본 풀 변경으로 인해 이 옵션은 더 이상 필요하지 않습니다. 세그폴트 오류가 발생하면 'forks'
풀로 전환해 보세요. 문제가 지속되면 재현과 함께 새 이슈를 열어주세요.
스위트 작업에서 빈 작업 제거됨
이는 고급 작업 API의 변경 사항입니다. 이전에는 .suite
를 순회하면 파일 작업 대신 사용되던 빈 내부 스위트로 연결되었습니다.
이로 인해 .suite
는 선택적으로 사용할 수 있습니다. 작업이 최상위 수준에서 정의되면 스위트가 없습니다. 이제 모든 작업(파일 작업 자체 포함)에 .file
속성이 있으므로, 무한 재귀에 빠지지 않도록 주의하세요.
이 변경 사항은 또한 expect.getState().currentTestName
에서 파일을 제거하고 expect.getState().testPath
를 필수로 만듭니다.
task.meta
가 JSON 리포터에 추가됩니다
JSON 리포터는 이제 모든 어설션 결과에 대해 task.meta
를 출력합니다.
모의 함수의 제네릭 타입 단순화 (예: vi.fn<T>
, Mock<T>
)
이전에는 vi.fn<TArgs, TReturn>
이 인자와 반환 값에 대해 두 개의 제네릭 타입을 각각 받았습니다. 이제 사용을 단순화하기 위해 함수 타입 vi.fn<T>
를 직접 받도록 변경되었습니다.
import { type Mock, vi } from 'vitest';
const add = (x: number, y: number): number => x + y;
// vi.fn<T> 사용
const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>();
const mockAdd = vi.fn<typeof add>();
// Mock<T> 사용
const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn();
const mockAdd: Mock<typeof add> = vi.fn();
해결된 mock.results
에 접근
이전에는 함수가 Promise를 반환할 경우 Vitest가 mock.results
값을 resolve했습니다. 이제 반환된 Promise가 해결되거나 거부될 때만 채워지는 별도의 mock.settledResults
속성이 있습니다.
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
const result = fn.mock.results[0]; // 'result'
const result = fn.mock.results[0]; // 'Promise<result>'
const settledResult = fn.mock.settledResults[0]; // 'result'
이 변경과 함께, 이전에 toHaveReturned
를 사용했다면 마이그레이션을 더 쉽게 하기 위해 toHaveReturned
와 유사한 새로운 toHaveResolved*
매처를 도입합니다.
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
expect(fn).toHaveReturned('result');
expect(fn).toHaveResolved('result');
브라우저 모드
Vitest 브라우저 모드는 베타 기간 동안 많은 변경 사항이 있었습니다. 브라우저 모드에 대한 우리의 철학은 GitHub 토론 페이지에서 읽을 수 있습니다.
대부분의 변경 사항은 추가적인 것이었지만, 몇 가지 작은 호환성 변경 사항이 있었습니다.
none
프로바이더가preview
로 이름이 변경되었습니다 #5842preview
프로바이더가 이제 기본값입니다 #5842indexScripts
가orchestratorScripts
로 이름이 변경되었습니다 #5842
사용되지 않는 옵션 제거됨
일부 사용되지 않는 옵션이 제거되었습니다.
vitest typecheck
명령어 - 대신vitest --typecheck
를 사용하세요VITEST_JUNIT_CLASSNAME
및VITEST_JUNIT_SUITE_NAME
환경 변수 (대신 리포터 옵션을 사용하세요)c8
커버리지 확인 (대신 coverage-v8을 사용하세요)vitest
에서SnapshotEnvironment
내보내기 - 대신vitest/snapshot
에서 가져오세요SpyInstance
는MockInstance
를 위해 제거되었습니다
Vitest 1.0으로 마이그레이션
최소 요구 사항
Vitest 1.0은 Vite 5.0 및 Node.js 18 이상을 필요로 합니다.
모든 @vitest/*
하위 패키지는 Vitest 버전 1.0을 필요로 합니다.
스냅샷 업데이트 #3961
스냅샷의 따옴표는 더 이상 이스케이프되지 않으며, 모든 스냅샷은 문자열이 한 줄이더라도 백틱 따옴표(`
)를 사용합니다.
- 따옴표는 더 이상 이스케이프되지 않습니다.
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
Object {
- \\"foo\\": \\"bar\\",
+ "foo": "bar",
}
`)
- 한 줄 스냅샷은 이제 "'" 따옴표 대신 "`" 따옴표를 사용합니다.
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)
또한 @vitest/snapshot
패키지에 변경 사항이 있었습니다. 직접 사용하지 않는다면 아무것도 변경할 필요가 없습니다.
equalityCheck
메서드를 재정의하기 위해 더 이상SnapshotClient
를 확장할 필요가 없습니다. 인스턴스를 초기화할 때isEqual
로 전달하기만 하면 됩니다.client.setTest
가client.startCurrentRun
으로 이름이 변경되었습니다.client.resetCurrent
가client.finishCurrentRun
으로 이름이 변경되었습니다.
풀 표준화 #4172
러너를 필요에 맞게 쉽게 구성할 수 있도록 많은 구성 옵션을 제거했습니다. --threads
또는 기타 관련 플래그에 의존하는 경우 마이그레이션 예제를 참조하세요.
--threads
는 이제--pool=threads
입니다.--no-threads
는 이제--pool=forks
입니다.--single-thread
는 이제--poolOptions.threads.singleThread
입니다.--experimental-vm-threads
는 이제--pool=vmThreads
입니다.--experimental-vm-worker-memory-limit
는 이제--poolOptions.vmThreads.memoryLimit
입니다.--isolate
는 이제--poolOptions.<pool-name>.isolate
및browser.isolate
입니다.test.maxThreads
는 이제test.poolOptions.<pool-name>.maxThreads
입니다.test.minThreads
는 이제test.poolOptions.<pool-name>.minThreads
입니다.test.useAtomics
는 이제test.poolOptions.<pool-name>.useAtomics
입니다.test.poolMatchGlobs.child_process
는 이제test.poolMatchGlobs.forks
입니다.test.poolMatchGlobs.experimentalVmThreads
는 이제test.poolMatchGlobs.vmThreads
입니다.
{
scripts: {
- "test": "vitest --no-threads"
// 동일한 동작을 위해:
+ "test": "vitest --pool forks --poolOptions.forks.singleFork"
// 또는 다중 병렬 포크:
+ "test": "vitest --pool forks"
}
}
{
scripts: {
- "test": "vitest --experimental-vm-threads"
+ "test": "vitest --pool vmThreads"
}
}
{
scripts: {
- "test": "vitest --isolate false"
+ "test": "vitest --poolOptions.threads.isolate false"
}
}
{
scripts: {
- "test": "vitest --no-threads --isolate false"
+ "test": "vitest --pool forks --poolOptions.forks.isolate false"
}
}
커버리지 변경 사항 #4265, #4442
coverage.all
옵션이 이제 기본적으로 활성화됩니다. 이는 coverage.include
패턴과 일치하는 모든 프로젝트 파일이 실행되지 않더라도 처리됨을 의미합니다.
커버리지 임계값 API의 형태가 변경되었으며, 이제 glob 패턴을 사용하여 특정 파일에 대한 임계값을 지정할 수 있습니다.
export default defineConfig({
test: {
coverage: {
- perFile: true,
- thresholdAutoUpdate: true,
- 100: true,
- lines: 100,
- functions: 100,
- branches: 100,
- statements: 100,
+ thresholds: {
+ perFile: true,
+ autoUpdate: true,
+ 100: true,
+ lines: 100,
+ functions: 100,
+ branches: 100,
+ statements: 100,
+ }
}
}
})
모의 타입 #4400
Jest 스타일의 "Mock" 명명 규칙을 따라 몇 가지 타입이 제거되었습니다.
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'
WARNING
SpyInstance
는 MockInstance
를 선호하여 더 이상 사용되지 않으며 다음 주요 릴리스에서 제거될 예정입니다.
타이머 모의 #3925
vi.useFakeTimers()
는 더 이상 process.nextTick
을 자동으로 모의(mock)하지 않습니다. vi.useFakeTimers({ toFake: ['nextTick'] })
을 사용하여 명시적으로 지정함으로써 process.nextTick
을 모의하는 것은 여전히 가능합니다.
그러나 --pool=forks
를 사용할 때는 process.nextTick
모의가 불가능합니다. process.nextTick
모의가 필요한 경우 다른 --pool
옵션을 사용하세요.
Jest에서 마이그레이션
Vitest는 Jest 호환 API로 설계되어 Jest에서 마이그레이션하는 것을 가능한 한 간단하게 만들었습니다. 이러한 노력에도 불구하고 다음과 같은 차이점에 직면할 수 있습니다.
기본값으로서의 전역
Jest는 기본적으로 전역 API를 활성화합니다. Vitest는 그렇지 않습니다. globals
구성 설정을 통해 전역을 활성화하거나 vitest
모듈에서 가져오기를 사용하도록 코드를 업데이트할 수 있습니다.
전역을 비활성화하기로 결정했다면, testing-library
와 같은 일반적인 라이브러리가 자동 DOM 정리를 실행하지 않는다는 점을 알아두세요.
모듈 모의
Jest에서 모듈을 모의할 때 팩토리 인수의 반환 값은 기본 내보내기입니다. Vitest에서는 팩토리 인수가 각 내보내기가 명시적으로 정의된 객체를 반환해야 합니다. 예를 들어, 다음 jest.mock
은 다음과 같이 업데이트해야 합니다.
jest.mock('./some-path', () => 'hello');
vi.mock('./some-path', () => ({
default: 'hello',
}));
자세한 내용은 vi.mock
API 섹션을 참조하세요.
자동 모의 동작
Jest와는 달리, <root>/__mocks__
에 있는 모의 모듈은 vi.mock()
이 호출되지 않는 한 로드되지 않습니다. Jest처럼 모든 테스트에서 모의되어야 하는 경우, setupFiles
내에서 모의할 수 있습니다.
모의된 패키지의 원본 가져오기
패키지를 부분적으로만 모의하는 경우 이전에 Jest의 함수 requireActual
을 사용했을 수 있습니다. Vitest에서는 이러한 호출을 vi.importActual
로 대체해야 합니다.
const { cloneDeep } = jest.requireActual('lodash/cloneDeep');
const { cloneDeep } = await vi.importActual('lodash/cloneDeep');
외부 라이브러리로 모의 확장
Jest는 기본적으로 이를 수행하지만, 모듈을 모의하고 이 모의를 동일한 모듈을 사용하는 다른 외부 라이브러리로 확장하려면, server.deps.inline을 사용하여 어떤 타사 라이브러리를 모의할지 명시적으로 지정해야 합니다. 이렇게 하면 외부 라이브러리가 소스 코드의 일부가 됩니다.
server.deps.inline: ["lib-name"]
expect.getState().currentTestName
Vitest의 test
이름은 스위트와 테스트를 더 쉽게 구별하기 위해 >
기호로 연결되는 반면, Jest는 공백()을 사용합니다.
- `${describeTitle} ${testTitle}`
+ `${describeTitle} > ${testTitle}`
환경 변수
Jest와 마찬가지로 Vitest는 NODE_ENV
가 설정되지 않은 경우 test
로 설정합니다. Vitest는 또한 JEST_WORKER_ID
에 해당하는 VITEST_POOL_ID
(항상 maxThreads
보다 작거나 같음)를 가지고 있으므로, 이에 의존하는 경우 이름을 변경하는 것을 잊지 마세요. Vitest는 또한 실행 중인 워커의 고유 ID인 VITEST_WORKER_ID
를 노출합니다. 이 값은 maxThreads
의 영향을 받지 않으며, 각 생성된 워커마다 증가합니다.
속성 교체
객체를 수정하려면 Jest에서 replaceProperty
API를 사용하지만, Vitest에서도 동일하게 vi.stubEnv
또는 vi.spyOn
을 사용할 수 있습니다.
Done 콜백
Vitest v0.10.0부터 테스트 선언 시 콜백 스타일은 더 이상 사용되지 않습니다. async
/await
함수를 사용하도록 다시 작성하거나 Promise를 사용하여 콜백 스타일을 모방할 수 있습니다.
it('should work', (done) => { // [!code --]
it('should work', () => new Promise(done => { // [!code ++]
// ...
done()
}) // [!code --]
})) // [!code ++]
훅
beforeAll
/beforeEach
훅은 Vitest에서 정리 함수를 반환할 수 있습니다. 이 때문에 undefined
또는 null
이외의 것을 반환하는 경우 훅 선언을 다시 작성해야 할 수 있습니다.
beforeEach(() => setActivePinia(createTestingPinia()));
beforeEach(() => {
setActivePinia(createTestingPinia());
});
Jest에서는 훅이 순차적으로(한 번에 하나씩) 호출됩니다. 기본적으로 Vitest는 훅을 병렬로 실행합니다. Jest의 동작을 사용하려면 sequence.hooks
옵션을 업데이트하세요.
export default defineConfig({
test: {
sequence: {
hooks: 'list',
},
},
});
타입
Vitest는 jest
네임스페이스와 동등한 것을 가지고 있지 않으므로, vitest
에서 직접 타입을 가져와야 합니다.
let fn: jest.Mock<(name: string) => number>;
import type { Mock } from 'vitest';
let fn: Mock<(name: string) => number>;
타이머
Vitest는 Jest의 레거시 타이머를 지원하지 않습니다.
타임아웃
jest.setTimeout
을 사용했다면 vi.setConfig
로 마이그레이션해야 합니다.
jest.setTimeout(5_000);
vi.setConfig({ testTimeout: 5_000 });
Vue 스냅샷
이것은 Jest 특정 기능은 아니지만, 이전에 vue-cli 프리셋과 함께 Jest를 사용했다면 jest-serializer-vue
패키지를 설치하고 setupFiles 내에서 사용해야 합니다.
import { defineConfig } from 'vite';
export default defineConfig({
test: {
setupFiles: ['./tests/unit/setup.js'],
},
});
import vueSnapshotSerializer from 'jest-serializer-vue';
expect.addSnapshotSerializer(vueSnapshotSerializer);
그렇지 않으면 스냅샷에 이스케이프된 "
문자가 많이 포함될 것입니다.