
๐งช ๋ณ๊ฒฝ ์ด์
Jest๋ Facebook์์ ๋ง๋ JavaScript ํ ์คํ ํ๋ ์์ํฌ๋ก, ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๊ณผ ์ํ๊ณ๋ฅผ ์๋ํ๋ค.
๊ทธ๋ฌ๋, ๋ด ํ๋ก์ ํธ์ ๊ฐ๋ฐ ํ๊ฒฝ์ธ Vite์๋ ๊ถํฉ์ด ์ข์ง ์์์ ์ฌ๋ฌ ์๋ฌ๋ค์ด ๋ฐ์ํ๋ค.
๊ทธ๋์ ์ ๋ฅผ ๋จน๋ ์ค์ ..๐คฏ
Vitest๋ Vite์ ๋น ๋ฅธ ๋ฒ๋ค๋ง์ ๊ทธ๋๋ก ํ์ฉํด์ ๋น ๋ฅธ ์คํ์ด ๊ฐ๋ฅํ๋ฉฐ,
Jest์ ์ ์ฌํ API๋ก ์ง์ ์ฅ๋ฒฝ์ด ๋ฎ์ ๋ฟ๋ง ์๋๋ผ
tsconfig, alias ๋ฑ์ ์ค์ ์ด Vite ์ค์ ๋ง์ผ๋ก ๋๋ถ๋ถ ํด๊ฒฐ์ด ๋๋ค๋ ๊ฒ์ ์๊ฒ ๋์๋ค.
๊ทธ๋์ Jest๋ฅผ ์ ๊ฑฐํ๊ณ Vitest๋ก ์ ํํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
๐ Jest ๐๐ป Vitest ๋ง์ด๊ทธ๋ ์ด์ ๋ฐฉ๋ฒ
1๏ธโฃ ๊ธฐ์กด Jest ๊ด๋ จ ์์กด์ฑ๋ค์ ๋ชจ๋ ์ ๊ฑฐํ๊ณ , Vitest ์ค์นํ๊ธฐ
pnpm remove jest ts-jest jest-environment-jsdom "@types/jest"
pnpm add -D vitest @vitest/coverage-v8 jsdom
2๏ธโฃ vitest.config.ts ์์ ํ๊ธฐ
import { defineConfig } from 'vitest/config';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import path from 'path';
import react from '@vitejs/plugin-react';
const __filename = fileURLToPath(import.meta.url); // ํ์ฌ ํ์ผ์ ์ ์ฒด ๊ฒฝ๋ก
const __dirname = dirname(__filename); // ํ์ฌ ํ์ผ์ด ์์นํ ๋๋ ํ ๋ฆฌ ๊ฒฝ๋ก
// Vite ์ค์
export default defineConfig({
// ์ฌ์ฉํ ํ๋ฌ๊ทธ์ธ ๋ชฉ๋ก
plugins: [react()],
// import ๊ฒฝ๋ก ๊ด๋ จ ์ค์
resolve: {
alias: {
// @์ 'src' ํด๋๋ก ๋งคํ๋๋๋ก ์ค์
'@': path.resolve(__dirname, './src'),
},
},
/* ๐ Vitest ์ ์ฉ ์ต์
*/
test: {
environment: 'jsdom',
globals: true,
setupFiles: './src/setupTests.ts',
coverage: {
provider: 'v8',
reporter: ['text', 'lcov'],
exclude: ['dist', 'node_modules'],
},
},
});
3๏ธโฃ ์ปค๋ฒ๋ฆฌ์ง ์ค์ ํ๊ธฐ
pnpm add -D @vitest/coverage-v8
4๏ธโฃ TypeScrip ์ ์ญ ํ์ ์ค์ ํ๊ธฐ
tsconfig.json์ compilerOptions ๋ธ๋ก ์์ types์ "vitest/globals"์ ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
๋ด ์ค์ ์ ๊ฒฝ์ฐ ์๋์ ๊ฐ๋ค.
{
"files": [],
"moduleResolution": "Node",
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"types": [
"vite/client",
"vitest/globals",
"node",
"@testing-library/jest-dom"
],
"jsx": "react-jsx",
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
5๏ธโฃ API ๋ณ๊ฒฝํ๊ธฐ (jest -> vi)
/* ์ํ */
// Before
jest.mock('@/apis/axios');
jest.fn();
// After
vi.mock('@/apis/axios');
vi.fn();
6๏ธโฃ ์ ์ญ CSS → CSS ๋ชจ๋ํ
Vitest๋ Jest์ ๋ฌ๋ฆฌ CSS ๋ชจ๋์ ์ง์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ๊ถ์ฅ๋๋ค๊ณ ํ๋ค.
/* ์ํ */
// Before
import '@/styles/LoginForm.css';
<div className="login-form">
// After
import styles from './LoginForm.module.css';
<div className={styles.form}>
7๏ธโฃ CI ํ๊ฒฝ ๋ช ๋ น ๋ณ๊ฒฝ
Vitest๋ Jest์ฒ๋ผ --ci ์ต์ ์ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์๋์ ๊ฐ์ด ๋ฐ๊ฟ์ฃผ์๋ค.
- name: Run Tests with Coverage
run: pnpm vitest run --coverage --passWithNoTests
๐ ๊ฒฐ๋ก
Jest๋ก ํ ์คํธ๋ฅผ ์งํํ๋ฉฐ ์๋ง์ ์๋ฌ ๋๋ฌธ์ ๊ณ ์ํ๋ ๊ณผ์ ์์
Vite ํ๋ก์ ํธ๋ผ๋ฉด Vitest๊ฐ ์ฌ์ค์ ํ์ค์ด๋ผ๊ณ ํ ์ ์์์ ์๊ฒ ๋์๋ค.. ๐
๋ฌด์์ ๋จ๋ค์ด ๋ง์ด ์ฌ์ฉํ๋ ๊ฑธ๋ก ํ๋ก์ ํธ๋ฅผ ํ๋๊ฒ ์๋๋ผ
ํ์คํ ์ฐพ์๋ณด๊ณ ์์ํด์ผ ๊ณ ์์ ๋ ํ๋ค๋ ๊ฑธ ๋ค์๊ธ ๋๋ ์ ์์๋ค ..ใ ใ
๋ํ, Jest์์ Vitest๋ก ์ฎ๊ธฐ๋ ๊ณผ์ ์ด ๋จ์ํด๋ณด์๋๋ฐ,
๋ง์ ํ๋์ฉ ๋ฐ๊พธ๋ค ๋ณด๋๊น ์ฌ๋ฌ ์๋ฌ์ ๋ง์ฃผ์ณค์ด์ ์ด๋ ๊ฒ ๊ณต์ ํ๊ฒ ๋์๋ค.
๋๊ตฐ๊ฐ์๊ฒ๋ ๋์์ด ๋๊ธธ ,,๐๐ป
'๐ป ํ๋ก์ ํธ > ๐ ํธ๋ฌ๋ธ์ํ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [ํธ๋ฌ๋ธ์ํ ] ์ค์๊ฐ ์๋ฆผ ์ ์กํ๊ธฐ (1) | 2025.07.07 |
|---|---|
| [ํธ๋ฌ๋ธ์ํ ] TypeScript์์ CSS / ์ด๋ฏธ์ง import ์ ์ค๋ฅ ๋ฐ์ (0) | 2025.06.14 |
| [ํธ๋ฌ๋ธ์ํ ] NPM์์ PNPM์ผ๋ก (0) | 2025.06.04 |
| [ํธ๋ฌ๋ธ์ํ ] GitHub Actions์์ vite: not found ์ค๋ฅ ํด๊ฒฐ (0) | 2025.05.23 |