VitestAdvanced Techniques: Claude Code 활용 가이드
vitestadvanced techniques: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.
Vitestで高品質な테스트スイートを구축する
VitestはViteベースの高速테스트프레임워크です。Jest互換のAPIに加え、TypeScriptのネイティブサポート、HMR대응の監視モードなど、モダンな개발体験を提供します。Claude Code는 複雑な테스트シナリオのコード생성に非常に優れています。
高度な모크戦略
Claude Code에모듈모크の설계を依頼합시다。
> 外部API클라이언트の모크を설계して。
> 요청・응답の타입チェック付き、에러ケースも含めて。
import { describe, it, expect, vi, beforeEach } from "vitest";
import { UserService } from "./user-service";
import { ApiClient } from "./api-client";
// 모듈모크
vi.mock("./api-client", () => ({
ApiClient: vi.fn().mockImplementation(() => ({
get: vi.fn(),
post: vi.fn(),
put: vi.fn(),
delete: vi.fn(),
})),
}));
describe("UserService", () => {
let service: UserService;
let mockClient: ReturnType<typeof vi.mocked<ApiClient>>;
beforeEach(() => {
vi.clearAllMocks();
mockClient = new ApiClient() as any;
service = new UserService(mockClient);
});
it("ユーザー一覧を取得する", async () => {
const mockUsers = [
{ id: "1", name: "Alice", email: "[email protected]" },
{ id: "2", name: "Bob", email: "[email protected]" },
];
vi.mocked(mockClient.get).mockResolvedValue({ data: mockUsers });
const result = await service.getUsers();
expect(mockClient.get).toHaveBeenCalledWith("/users");
expect(result).toEqual(mockUsers);
});
it("APIエラー時にカスタム例外をスローする", async () => {
vi.mocked(mockClient.get).mockRejectedValue(
new Error("Network Error")
);
await expect(service.getUsers()).rejects.toThrow("ユーザーの取得に失敗しました");
});
});
매개변수테스트(test.each)
同じロジックを複数の매개변수で검증するパターンです。
describe("バリデーション関数", () => {
it.each([
{ input: "[email protected]", expected: true },
{ input: "[email protected]", expected: true },
{ input: "invalid-email", expected: false },
{ input: "@no-local.com", expected: false },
{ input: "no-domain@", expected: false },
{ input: "", expected: false },
])("isValidEmail($input) => $expected", ({ input, expected }) => {
expect(isValidEmail(input)).toBe(expected);
});
it.each`
password | minLength | hasUpper | hasNumber | expected
${"Abc12345"} | ${8} | ${true} | ${true} | ${true}
${"abc12345"} | ${8} | ${false} | ${true} | ${false}
${"short"} | ${8} | ${false} | ${false} | ${false}
${"NoNumbers"} | ${8} | ${true} | ${false} | ${false}
`(
"パスワード強度チェック: $password",
({ password, expected }) => {
expect(isStrongPassword(password)).toBe(expected);
}
);
});
カスタムマッチャーの생성
프로젝트固有の어설션を定義할 수 있습니다。
// vitest.setup.ts
import { expect } from "vitest";
expect.extend({
toBeWithinRange(received: number, floor: number, ceiling: number) {
const pass = received >= floor && received <= ceiling;
return {
message: () =>
`expected ${received} to be within range ${floor} - ${ceiling}`,
pass,
};
},
toBeValidDate(received: string) {
const date = new Date(received);
const pass = !isNaN(date.getTime());
return {
message: () => `expected "${received}" to be a valid date string`,
pass,
};
},
toMatchApiResponse(received: unknown) {
const pass =
typeof received === "object" &&
received !== null &&
"data" in received &&
"meta" in received;
return {
message: () => `expected value to match API response shape`,
pass,
};
},
});
// 타입定義
declare module "vitest" {
interface Assertion<T = any> {
toBeWithinRange(floor: number, ceiling: number): void;
toBeValidDate(): void;
toMatchApiResponse(): void;
}
}
스냅샷테스트の활용
컴포넌트や데이터構造の스냅샷테스트です。
import { render } from "@testing-library/react";
describe("UserProfile", () => {
it("プロフィールカードが正しくレンダリングされる", () => {
const { container } = render(
<UserProfile
user={{
id: "1",
name: "テストユーザー",
email: "[email protected]",
role: "admin",
}}
/>
);
expect(container).toMatchSnapshot();
});
it("インラインスナップショットでAPIレスポンスを検証", () => {
const response = transformUserResponse(rawData);
expect(response).toMatchInlineSnapshot(`
{
"displayName": "テストユーザー",
"email": "[email protected]",
"isAdmin": true,
}
`);
});
});
테스트커버리지の최적화
// vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
coverage: {
provider: "v8",
reporter: ["text", "json", "html", "lcov"],
include: ["src/**/*.{ts,tsx}"],
exclude: [
"src/**/*.d.ts",
"src/**/*.test.{ts,tsx}",
"src/**/*.stories.{ts,tsx}",
"src/types/**",
"src/**/index.ts",
],
thresholds: {
statements: 80,
branches: 75,
functions: 80,
lines: 80,
},
},
setupFiles: ["./vitest.setup.ts"],
environment: "jsdom",
globals: true,
},
});
비동기테스트のパターン
タイマーや이벤트待機など、비동기処理の테스트手法です。
describe("非同期処理のテスト", () => {
it("デバウンス関数が正しく動作する", async () => {
vi.useFakeTimers();
const fn = vi.fn();
const debounced = debounce(fn, 300);
debounced("a");
debounced("b");
debounced("c");
expect(fn).not.toHaveBeenCalled();
vi.advanceTimersByTime(300);
expect(fn).toHaveBeenCalledTimes(1);
expect(fn).toHaveBeenCalledWith("c");
vi.useRealTimers();
});
it("リトライロジックが正しく動作する", async () => {
const fn = vi
.fn()
.mockRejectedValueOnce(new Error("1回目失敗"))
.mockRejectedValueOnce(new Error("2回目失敗"))
.mockResolvedValue("成功");
const result = await retry(fn, { maxAttempts: 3, delay: 100 });
expect(result).toBe("成功");
expect(fn).toHaveBeenCalledTimes(3);
});
});
정리
Vitestは高速な実行速度とモダンなAPIにより、테스트개발の体験を大きく向上させます。Claude Codeを활용すれば、모크설계、매개변수테스트、カスタムマッチャーなどの高度な테스트パターンも빠르게구현가능합니다。
E2E 테스트の구현はPlaywright E2E 테스트実践가이드を、API모크의 상세 정보는MSW API모크활용가이드를 참고하세요.Vitest공식 문서도 확인해 두세요.
무료 PDF: 5분 완성 Claude Code 치트시트
이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.
개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Claude Code/Codex 안전 Agent Harness 설계: 권한, 검증, 롤백
Claude Code와 Codex를 안전하게 운영하기 위한 Agent Harness를 권한 정책, 실행 계획, 검증, 복구 계층으로 설계합니다.
Claude Code 서브에이전트 활용 패턴 10선
Claude Code의 서브에이전트 기능을 활용하는 10가지 실전 패턴. 병렬 처리, 전문화, 컨텍스트 분리로 개발 속도를 두 배로 만드는 방법.
Claude Code Agent SDK 입문 ― 자율 에이전트를 빠르게 구축하는 방법
Claude Code Agent SDK로 자율형 AI 에이전트를 구축하는 방법을 해설합니다. 설정부터 도구 정의, 멀티스텝 실행까지 실전 코드와 함께 소개합니다.