AI.zip
  • AI 모델
  • 방법론
  • AI 서비스
  • 가격 비교
  • 블로그

AI.zip

AI 모델, 서비스, 방법론을 큐레이션하는 에디토리얼 플랫폼

탐색

  • AI 모델
  • AI 서비스
  • 방법론
  • 블로그

커뮤니티

  • 소개
  • 디스코드 참여
  • 문의

법적고지

  • 이용약관
  • 개인정보처리방침

© 2026 ai.zip. All rights reserved.

Discord 커뮤니티
블로그AI 시대의 테스트 자동화: LLM으로 테스트 코드 생성하기

AI 시대의 테스트 자동화: LLM으로 테스트 코드 생성하기

튜토리얼
2026년 3월 28일약 1분

핵심 포인트

  • 1.AI가 테스트 작성을 바꾸는 방법 개발자가 가장 싫어하는 작업 중 하나가 테스트 작성입니다
  • 2.LLM은 코드를 분석해 엣지 케이스를 찾고 테스트를 자동 생성할 수 있습니다
  • 3.pytest 테스트 자동 생성 실제 생성 예시입력 코드: AI 생성 테스트: JavaScript/TypeScript 테스트 생성 typescript {ts_source} Playwright E2E 테스트 자동 생성 커버리지 기반 테스트 보강 뮤테이션 테스트로 테스트 품질 검증 CI/CD 파이프라인에 AI 테스트 생성을 포함하면 신규 기능 추가 시 자동으로 테스트 스켈레톤이 생성됩니다.

AI가 테스트 작성을 바꾸는 방법

개발자가 가장 싫어하는 작업 중 하나가 테스트 작성입니다. LLM은 코드를 분석해 엣지 케이스를 찾고 테스트를 자동 생성할 수 있습니다.

mermaid
flowchart LR
    Code[소스 코드] --> LLM[LLM 분석]
    LLM --> Unit[단위 테스트]
    LLM --> Edge[엣지 케이스]
    LLM --> Mock[Mock 코드]
    Unit --> Coverage[커버리지 리포트]
    Edge --> Coverage
    Mock --> Coverage

pytest 테스트 자동 생성

python
import anthropic
import ast
import inspect

client = anthropic.Anthropic()

def generate_pytest_tests(source_code: str, module_name: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6-20251001",
        max_tokens=4096,
        system='''당신은 Python 테스트 전문가입니다.
        주어진 코드에 대해 pytest 테스트를 작성하세요.

        규칙:
        - 모든 public 함수/메서드 테스트
        - 정상 케이스 + 엣지 케이스 + 예외 케이스 포함
        - fixture 적극 활용
        - parametrize로 다양한 입력값 테스트
        - 테스트 이름은 test_함수명_상황 형식
        - Mock은 pytest-mock 사용''',
        messages=[{
            "role": "user",
            "content": f"다음 Python 코드에 대한 pytest 테스트를 작성해주세요:

{source_code}

모듈명: {module_name}"
        }]
    )
    return response.content[0].text

# 사용
with open("src/user_service.py") as f:
    source = f.read()

tests = generate_pytest_tests(source, "user_service")

with open("tests/test_user_service.py", "w") as f:
    f.write(tests)

print("테스트 파일 생성 완료")

실제 생성 예시입력 코드:

python
def calculate_discount(price: float, discount_pct: float) -> float:
    if discount_pct < 0 or discount_pct > 100:
        raise ValueError("할인율은 0-100 사이여야 합니다")
    return price * (1 - discount_pct / 100)

AI 생성 테스트:

python
import pytest
from pricing import calculate_discount

class TestCalculateDiscount:
    @pytest.mark.parametrize("price,pct,expected", [
        (10000, 10, 9000.0),
        (50000, 50, 25000.0),
        (100, 100, 0.0),
        (100, 0, 100.0),
    ])
    def test_normal_cases(self, price, pct, expected):
        assert calculate_discount(price, pct) == expected

    @pytest.mark.parametrize("invalid_pct", [-1, 101, -100, 200])
    def test_invalid_discount_raises(self, invalid_pct):
        with pytest.raises(ValueError, match="할인율은 0-100"):
            calculate_discount(10000, invalid_pct)

    def test_zero_price(self):
        assert calculate_discount(0, 50) == 0.0

    def test_float_precision(self):
        result = calculate_discount(1.0, 33.33)
        assert abs(result - 0.6667) < 0.001

JavaScript/TypeScript 테스트 생성

python
def generate_jest_tests(ts_source: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6-20251001",
        max_tokens=4096,
        system='''TypeScript/Jest 테스트 전문가로서:
        - describe/it 구조 사용
        - beforeEach/afterEach로 설정
        - jest.mock()으로 의존성 모킹
        - async/await 패턴
        - expect(fn).toThrow() 예외 테스트
        - 타입 안전성 고려''',
        messages=[{"role": "user", "content": f"Jest 테스트 작성:
```typescript
{ts_source}
```"}]
    )
    return response.content[0].text

Playwright

E2E 테스트 자동 생성

python
def generate_playwright_tests(page_description: str, user_flows: list[str]) -> str:
    flows_text = "
".join(f"- {flow}" for flow in user_flows)

    response = client.messages.create(
        model="claude-sonnet-4-6-20251001",
        max_tokens=4096,
        system='''Playwright E2E 테스트 전문가:
        - page.locator() 사용 (XPath 지양)
        - await expect() 단언문
        - 스크린샷으로 시각적 검증
        - 네트워크 요청 인터셉트
        - 모바일/데스크톱 뷰포트 테스트''',
        messages=[{
            "role": "user",
            "content": f'''페이지: {page_description}
테스트할 사용자 흐름:
{flows_text}

Playwright TypeScript 테스트를 작성해주세요.'''
        }]
    )
    return response.content[0].text

# 로그인 페이지 테스트 생성
tests = generate_playwright_tests(
    page_description="이메일/비밀번호 로그인 페이지",
    user_flows=[
        "정상 로그인 후 대시보드 이동",
        "잘못된 비밀번호 입력 시 에러 메시지",
        "이메일 미입력 시 필드 검증",
        "비밀번호 찾기 링크 클릭",
    ]
)

커버리지 기반 테스트 보강

python
import subprocess
import re

def find_uncovered_lines(source_file: str) -> list[int]:
    # pytest-cov 실행
    result = subprocess.run(
        ["pytest", "--cov", source_file.replace(".py", ""),
         "--cov-report", "term-missing", "-q"],
        capture_output=True, text=True
    )

    # 미커버 라인 파싱
    match = re.search(r'TOTAL.*?(\d+)%.*?Missing: ([\d, ]+)', result.stdout)
    if match:
        missing_lines = [int(l) for l in match.group(2).split(', ')]
        return missing_lines
    return []

def generate_tests_for_uncovered(source_file: str, missing_lines: list[int]) -> str:
    with open(source_file) as f:
        lines = f.readlines()

    uncovered_code = ''.join(lines[max(0, l-3):l+3] for l in missing_lines[:10])

    response = client.messages.create(
        model="claude-sonnet-4-6-20251001",
        max_tokens=2048,
        messages=[{
            "role": "user",
            "content": f"다음 미커버 코드 라인에 대한 테스트를 추가해줘:

{uncovered_code}"
        }]
    )
    return response.content[0].text

뮤테이션 테스트로 테스트 품질 검증

bash
# mutmut으로 뮤테이션 테스트
pip install mutmut
mutmut run --paths-to-mutate src/

# 살아남은 뮤턴트 확인
mutmut results

# AI에게 살아남은 뮤턴트 제거 요청
mutmut show 5  # 5번 뮤턴트 상세 보기
python
def kill_surviving_mutants(mutant_diff: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6-20251001",
        max_tokens=1024,
        messages=[{
            "role": "user",
            "content": f'''이 뮤턴트를 잡는 테스트를 작성해줘:
뮤턴트 diff:
{mutant_diff}'''
        }]
    )
    return response.content[0].text

CI/CD 파이프라인에 AI 테스트 생성을 포함하면 신규 기능 추가 시 자동으로 테스트 스켈레톤이 생성됩니다.

이 글에서 다루는 AI

Anthropic: Claude Sonnet 4.5

Anthropic · 모델

OpenAI: GPT-4o

OpenAI · 모델

Anthropic: Claude Haiku 4.5

Anthropic · 모델

관련 글 더 보기

가이드2026년 4월 6일

AI 재귀적 자기 개선 완전 가이드: 특이점 논쟁부터 실전 활용까지

비교2026년 4월 6일

Cursor vs GitHub Copilot vs Windsurf: AI 코딩 어시스턴트 비교 (2026)

비교2026년 4월 6일

GPT-5.4 vs Claude Opus 4.6 vs Gemini 2.5 Pro: 2026 플래그십 AI 비교

비교2026년 4월 6일

Auto Research vs AutoML: LLM 자율 연구와 자동 ML의 핵심 차이

ai.zip 커뮤니티에 참여하세요

AI 소식·유용한 링크 공유, 새 모델/서비스 토론까지 -- Discord에서 함께해요.

Discord 참여하기

이전글

AI 기반 시맨틱 검색 엔진 구축하기: 하이브리드 검색 완전 가이드

다음글

AI 문서 자동화: 코드에서 문서 생성하고 유지하는 방법

댓글

0개

댓글을 작성하려면

로그인

해주세요

글 정보

튜토리얼
2026년 3월 28일1분

관련 글

AI 재귀적 자기 개선 완전 가이드: 특이점 논쟁부터 실전 활용까지

가이드

Cursor vs GitHub Copilot vs Windsurf: AI 코딩 어시스턴트 비교 (2026)

비교

GPT-5.4 vs Claude Opus 4.6 vs Gemini 2.5 Pro: 2026 플래그십 AI 비교

Foundation Model API Strategy

방법론

Agentic Workflow

방법론

Plan Mode Workflow

Agentic Workflow

비교

Auto Research vs AutoML: LLM 자율 연구와 자동 ML의 핵심 차이

비교

Cursor vs Claude Code vs Copilot: 2026 AI 코딩 어시스턴트 최종 비교

비교

관련 모델

Anthropic: Claude Sonnet 4.5

Anthropic

OpenAI: GPT-4o

OpenAI

Anthropic: Claude Haiku 4.5

Anthropic

관련 방법론

Foundation Model API Strategy

Agentic Workflow

Plan Mode Workflow

Agentic Workflow