테스트 전략 완전 가이드: Claude Code 활용
테스트 피라미드를 기반으로 Claude Code로 단위 테스트, 통합 테스트, E2E 테스트를 설계하고 구현하는 실전 가이드입니다.
Claude Code로 테스트 전략 설계하고 구현하기
테스트는 쓰는 편이 좋다는 걸 알아도 어느 수준까지, 무엇을 테스트할지 판단하기는 어렵습니다. Claude Code를 활용하면 테스트 피라미드를 기반으로 전략적인 테스트 설계와 구현을 효율적으로 진행할 수 있습니다.
테스트 피라미드 실천
> 프로젝트 테스트 전략을 제안해줘.
> 테스트 피라미드를 기반으로
> 단위 테스트, 통합 테스트, E2E 테스트의
> 비율과 대상을 정리해줘.
| 테스트 종류 | 비율 | 대상 | 도구 |
|---|---|---|---|
| 단위 테스트 | 70% | 비즈니스 로직, 유틸 | Vitest |
| 통합 테스트 | 20% | API, DB 연동, 컴포넌트 | Vitest + Testing Library |
| E2E 테스트 | 10% | 주요 사용자 플로우 | Playwright |
단위 테스트 자동 생성
> src/services/ 아래 모든 함수의 단위 테스트를 생성해줘.
> 정상 케이스, 예외 케이스, 경계값까지 커버.
> 커버리지 80% 이상을 목표로.
// src/services/pricing.ts
export function calculatePrice(
basePrice: number,
quantity: number,
discountRate: number
): number {
if (quantity < 0) throw new Error("수량은 0 이상이어야 합니다");
if (discountRate < 0 || discountRate > 1) {
throw new Error("할인율은 0~1 범위여야 합니다");
}
const subtotal = basePrice * quantity;
return Math.round(subtotal * (1 - discountRate));
}
// __tests__/services/pricing.test.ts
import { describe, it, expect } from "vitest";
import { calculatePrice } from "../../services/pricing";
describe("calculatePrice", () => {
// 정상 케이스
it("기본 단가 × 수량을 반환한다", () => {
expect(calculatePrice(100, 5, 0)).toBe(500);
});
it("할인을 적용한다", () => {
expect(calculatePrice(1000, 1, 0.1)).toBe(900);
});
it("소수점을 반올림한다", () => {
expect(calculatePrice(333, 3, 0.1)).toBe(899);
});
// 경계값
it("수량이 0이면 0을 반환한다", () => {
expect(calculatePrice(100, 0, 0)).toBe(0);
});
it("할인율 100%이면 0을 반환한다", () => {
expect(calculatePrice(100, 5, 1)).toBe(0);
});
// 예외 케이스
it("음수 수량은 에러를 던진다", () => {
expect(() => calculatePrice(100, -1, 0)).toThrow("수량은 0 이상");
});
it("범위를 벗어난 할인율은 에러를 던진다", () => {
expect(() => calculatePrice(100, 1, 1.5)).toThrow("할인율");
expect(() => calculatePrice(100, 1, -0.1)).toThrow("할인율");
});
});
통합 테스트 생성
API 엔드포인트에 대한 통합 테스트를 생성합니다.
> /api/orders 엔드포인트의 통합 테스트를 만들어줘.
> 테스트용 DB로 실제 CRUD 동작을 검증하도록.
> 테스트 간 데이터 간섭이 없도록 해줘.
import { describe, it, expect, beforeEach, afterAll } from "vitest";
import request from "supertest";
import { app } from "../../app";
import { prisma } from "../../lib/prisma";
describe("Orders API Integration", () => {
beforeEach(async () => {
await prisma.order.deleteMany();
await prisma.user.upsert({
where: { id: "test-user" },
update: {},
create: { id: "test-user", email: "test@example.com", name: "Test" },
});
});
afterAll(async () => {
await prisma.$disconnect();
});
it("POST /api/orders 로 주문을 생성할 수 있다", async () => {
const res = await request(app)
.post("/api/orders")
.set("Authorization", "Bearer test-token")
.send({
items: [{ productId: "P1", quantity: 2, price: 1000 }],
});
expect(res.status).toBe(201);
expect(res.body.data.id).toBeDefined();
expect(res.body.data.totalAmount).toBe("2000");
});
it("GET /api/orders 로 주문 목록을 가져올 수 있다", async () => {
// 테스트 데이터 준비
await prisma.order.create({
data: {
userId: "test-user",
totalAmount: 5000,
status: "confirmed",
},
});
const res = await request(app)
.get("/api/orders")
.set("Authorization", "Bearer test-token");
expect(res.status).toBe(200);
expect(res.body.data).toHaveLength(1);
});
});
E2E 테스트 생성
Playwright로 주요 사용자 플로우를 테스트합니다.
> 회원가입부터 로그인까지의 E2E 테스트를
> Playwright로 작성해줘.
import { test, expect } from "@playwright/test";
test.describe("회원가입 & 로그인 플로우", () => {
test("신규 가입 후 대시보드까지 이동", async ({ page }) => {
// 회원가입 페이지 접속
await page.goto("/register");
await expect(page.getByRole("heading", { name: "회원가입" })).toBeVisible();
// 폼 입력
await page.getByLabel("이메일").fill("newuser@example.com");
await page.getByLabel("비밀번호").fill("SecurePass123");
await page.getByLabel("비밀번호 확인").fill("SecurePass123");
// 가입 실행
await page.getByRole("button", { name: "가입" }).click();
// 대시보드로 리다이렉트
await expect(page).toHaveURL("/dashboard");
await expect(page.getByText("환영합니다")).toBeVisible();
});
test("유효하지 않은 이메일이면 에러가 표시된다", async ({ page }) => {
await page.goto("/register");
await page.getByLabel("이메일").fill("invalid-email");
await page.getByRole("button", { name: "가입" }).click();
await expect(page.getByText("유효한 이메일")).toBeVisible();
});
});
테스트 커버리지 개선
> 테스트 커버리지 리포트를 생성하고
> 커버리지가 낮은 파일에 테스트를 추가해줘.
> 목표 80% 이상.
# Claude Code가 실행하는 명령
npx vitest --coverage --run
TDD 기반 테스트 우선 개발은 TDD와 Claude Code의 궁합, CI/CD의 자동 실행은 CI/CD 파이프라인 구축 가이드, 디버깅에서의 테스트 활용은 디버깅 테크닉 완전 가이드에서 다루고 있습니다.
정리
테스트 전략의 핵심은 “무엇을 어떤 레벨에서 테스트할지”를 잘 정하는 것입니다. Claude Code에 테스트 피라미드를 의식하도록 지시하면 효율적이고 유효한 테스트 체계를 구축할 수 있습니다. 우선 단위 테스트부터 시작해 점진적으로 커버리지를 넓혀 가 보세요.
테스트 프레임워크의 자세한 내용은 Vitest 공식 문서, Claude Code에 대해서는 Anthropic 공식 문서를 참고하세요.
Claude Code 워크플로우를 한 단계 업그레이드하세요
지금 바로 Claude Code에 복사해 쓸 수 있는 검증된 프롬프트 템플릿 50선.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Claude Code Agent SDK 입문 ― 자율 에이전트를 빠르게 구축하는 방법
Claude Code Agent SDK로 자율형 AI 에이전트를 구축하는 방법을 해설합니다. 설정부터 도구 정의, 멀티스텝 실행까지 실전 코드와 함께 소개합니다.
Claude Code 컨텍스트 관리 테크닉 완전 가이드
Claude Code의 컨텍스트 윈도우를 최대한 활용하는 실전 테크닉을 해설합니다. 토큰 절약, 대화 분할, CLAUDE.md 활용법까지 소개합니다.
Claude Code MCP Server 설정 및 실전 활용 가이드
Claude Code의 MCP Server 기능을 종합적으로 소개합니다. 외부 도구 연결, 서버 설정, 실전 통합 사례까지 한 번에 알아보세요.