Vitest
Vitest는 Vite 생태계의 테스트 러너입니다. Turborepo와 통합하면 엄청난 속도 향상을 얻을 수 있습니다.
Vitest 문서는 하나의 루트 명령에서 monorepo의 모든 테스트를 실행하는 "Vitest Projects" 구성을 만드는 방법을 보여줍니다. 이는 병합된 커버리지 보고서와 같은 동작을 즉시 가능하게 합니다. 이 기능은 monorepo에 대한 현대적인 모범 사례를 따르지 않는데, Jest와의 호환성을 위해 설계되었기 때문입니다(Jest의 Workspace 기능은 패키지 관리자 Workspaces 이전에 구축되었습니다).
Vitest는 projects를 위해 workspaces를 더 이상 사용하지 않습니다. projects를
사용할 때 개별 프로젝트 vitest 구성은 projects 구성을 상속하므로 더 이상 루트
구성을 확장할 수 없습니다. 대신 vitest.shared.ts와 같은 별도의 공유 파일이
필요합니다.
이 때문에 각각 고유한 장단점이 있는 두 가지 옵션이 있습니다:
캐싱을 위한 Turborepo 활용
캐시 적중률을 개선하고 변경된 테스트만 실행하려면 패키지별로 작업을 구성하여 Vitest 명령을 각 패키지의 별도 캐시 가능한 스크립트로 분할할 수 있습니다. 이 속도는 병합된 커버리지 보고서를 직접 만들어야 한다는 절충안을 수반합니다.
완전한 예제를 보려면 npx create-turbo@latest --example with-vitest를
실행하거나 예제의 소스 코드를
방문하세요.
설정
다음과 같은 간단한 패키지 관리자 Workspace가 있다고 가정해 봅시다:
apps/web과 packages/ui 모두 자체 테스트 스위트가 있으며, vitest가 사용하는 패키지에 설치됩니다. package.json 파일에는 Vitest를 실행하는 test 스크립트가 포함되어 있습니다:
루트 turbo.json 내부에 test 작업을 만듭니다:


이제 turbo run test는 각 패키지의 모든 테스트 스위트를 병렬화하고 캐시하여 변경된 코드만 테스트합니다.
watch 모드에서 테스트 실행
CI에서 테스트 스위트를 실행하면 결과를 기록하고 완료 시 종료됩니다. 즉, Turborepo로 캐시할 수 있습니다. 그러나 개발 중에 Vitest의 watch 모드를 사용하여 테스트를 실행하면 프로세스가 종료되지 않습니다. 이로 인해 watch 작업은 장기 실행 개발 작업과 더 비슷합니다.
이러한 차이로 인해 두 개의 별도 Turborepo 작업을 지정하는 것을 권장합니다: 하나는 테스트를 실행하는 것이고, 다른 하나는 watch 모드에서 실행하는 것입니다.
아래 전략은 두 가지 작업을 만듭니다. 하나는 로컬 개발용이고 다른 하나는
CI용입니다. 로컬 개발용으로 test 작업을 만들고 대신 test:ci 작업을 만들
수도 있습니다.
예를 들어, 각 워크스페이스의 package.json 파일 내부에:
그리고 루트 turbo.json 내부에:


이제 global turbo를 사용하여 turbo run test:watch로 작업을 실행하거나 루트 package.json의 스크립트에서 실행할 수 있습니다:
병합된 커버리지 보고서 생성
Vitest의 Projects 기능은 모든 패키지의 테스트 커버리지 보고서를 병합하는 즉시 사용 가능한 커버리지 보고서를 생성합니다. 하지만 Turborepo 전략을 따르는 경우 커버리지 보고서를 직접 병합해야 합니다.
with-vitest
예제는
여러분의 요구에 맞게 적용할 수 있는 완전한 예제를 보여줍니다. npx create-turbo@latest --example with-vitest를 사용하여 빠르게 시작할 수
있습니다.
이를 수행하려면 다음과 같은 일반적인 단계를 따릅니다:
turbo run test를 실행하여 커버리지 보고서를 생성합니다.nyc merge로 커버리지 보고서를 병합합니다.nyc report를 사용하여 보고서를 생성합니다.
이를 수행할 Turborepo 작업은 다음과 같습니다:


이를 설정한 후 turbo test && turbo report를 실행하여 병합된 커버리지 보고서를 생성합니다.
with-vitest
예제는
여러분의 요구에 맞게 적용할 수 있는 완전한 예제를 보여줍니다. npx create-turbo@latest --example with-vitest를 사용하여 빠르게 시작할 수
있습니다.
Vitest의 Projects 기능 사용
Vitest Projects 기능은 패키지 관리자 Workspace와 동일한 모델을 따르지 않습니다. 대신 각 패키지의 테스트를 처리하기 위해 저장소의 각 패키지에 도달하는 루트 스크립트를 사용합니다.
이 모델에서는 현대 JavaScript 생태계 관점에서 패키지 경계가 없습니다. 이는 Turborepo가 이러한 패키지 경계에 의존하기 때문에 Turborepo의 캐싱을 신뢰할 수 없다는 것을 의미합니다.
이 때문에 Turborepo를 사용하여 테스트를 실행하려면 Root Tasks를 사용해야 합니다. Vitest Projects 설정을 구성한 후 Turborepo용 Root Tasks를 만듭니다:


특히 Root Task의 파일 입력에는 기본적으로 모든 패키지가 포함되므로 어떤 패키지에서든 변경이 발생하면 캐시 미스가 발생합니다. 이는 병합된 커버리지 보고서를 생성하기 위한 간단한 구성을 만들지만, 반복되는 작업을 캐시할 수 있는 기회를 놓치게 됩니다.
하이브리드 접근 방식 사용
하이브리드 솔루션을 구현하여 두 접근 방식의 이점을 결합할 수 있습니다. 이 접근 방식은 Vitest의 Projects 기능을 사용하여 로컬 개발을 통합하면서 CI에서 Turborepo의 캐싱을 보존합니다. 이는 약간 더 많은 구성과 저장소에서 혼합된 작업 실행 모델이라는 트레이드오프를 수반합니다.
먼저 projects를 사용할 때 개별 프로젝트가 루트 구성을 확장할 수 없으므로 공유 구성 패키지를 만듭니다. 공유 Vitest 구성을 위한 새 패키지를 만듭니다:
그런 다음 projects를 사용하여 루트 Vitest 구성을 만듭니다:
이 설정에서 패키지는 공유 구성을 가져오는 개별 Vitest 구성을 유지합니다. 먼저 공유 구성 패키지를 설치합니다:
그런 다음 Vitest 구성을 만듭니다:
turbo.json을 업데이트하여 종속성 그래프에 새 구성 패키지를 포함해야 합니다:


루트 package.json은 전역적으로 테스트를 실행하기 위한 스크립트를 포함합니다:
이 구성을 통해 개발자는 Vitest projects를 사용하여 원활한 로컬 개발 경험을 위해 루트에서 pnpm test:projects 또는 pnpm test:projects:watch를 실행할 수 있으며, CI는 패키지 수준 캐싱을 활용하기 위해 계속 turbo run test를 사용합니다. 이전 섹션에서 설명한 대로 병합된 커버리지 보고서를 여전히 수동으로 처리해야 합니다.