0Pricing
Claude Architect · 강의

테스트 생성 및 표준

생성되는 테스트의 품질을 높이도록 픽스처와 표준을 문서화합니다

테스트 생성 및 표준은(는) CoddyKit의 무료 Claude Architect 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Claude Architect 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why Generated Tests Drift

Ask Claude Code to "write tests for this module" with no guidance and you get tests that run but don't match your house style: wrong framework helpers, invented fixtures, assertions that mirror the implementation instead of the contract.

The fix is not a better one-off prompt. It is persistent, shared standards the model reads on every run. This lesson shows how to document fixtures and conventions so generated tests come out idiomatic, deterministic, and reviewable, in interactive sessions and in CI alike.

Standards Live in Project-Scope CLAUDE.md

Test conventions belong in project-level config so every contributor and every CI runner sees them. Put them in ./CLAUDE.md or .claude/CLAUDE.md, which is shared via VCS.

Do NOT rely on user-level ~/.claude/CLAUDE.md: it is personal, NOT shared through version control, so new teammates and your pipeline simply won't have it. Anything your test generation depends on must live in project scope.

# ./CLAUDE.md  (committed -> every dev + CI sees it)

## Testing standards
- Framework: pytest; one test file per module as tests/test_<module>.py
- Name tests test_<behavior>_<condition>_<expected>
- Assert on the public contract, never on private internals
- No network or real time in unit tests; use the provided fixtures

Modularize with @path Imports

A monolithic CLAUDE.md grows unreadable and burns context. Pull the detailed testing playbook into its own file and import it with @path syntax. This keeps the root file lean while still loading the standard.

The imported file is just markdown, version-controlled like everything else, so the standard is reusable and easy to review in isolation.

# ./CLAUDE.md
@./standards/testing-style.md
@./standards/fixtures.md

# Each imported file documents one slice of the standard,
# keeping the root CLAUDE.md short and scannable.

Load Test Rules Only When Needed

Even better than always-on imports: put test conventions in a .claude/rules/ file with YAML frontmatter paths. The rule loads only when editing matching files, so you save context and tokens versus a monolithic CLAUDE.md that ships everything on every turn.

Scope a rule to your test directory and it activates exactly when Claude is generating or editing tests, and stays out of the way otherwise.

# .claude/rules/testing.md
---
paths:
  - "tests/**"
  - "**/*.test.ts"
---
# Loaded only when a matching test file is in play
- Arrange-Act-Assert, one logical assertion per test
- Reuse fixtures from conftest.py; never hand-roll a DB
- Cover the happy path, one edge case, and one failure case

Document Fixtures as the Source of Truth

The single biggest cause of bad generated tests is invented fixtures: the model fabricates a user object or a DB stub instead of using yours. Document the real fixtures so Claude reuses them.

Spell out what each fixture provides, its shape, and when to use it. Treat this like a tool description: purpose, return value, input format, and applicability boundaries are what drive correct selection.

# ./standards/fixtures.md  (imported into CLAUDE.md)

## Available pytest fixtures (use these, do NOT invent)
- `db`        -> in-memory SQLite session, auto-rolled-back per test
- `client`    -> FastAPI TestClient with auth middleware disabled
- `user`      -> a persisted User(id=1, role="member"); returns the ORM obj
- `frozen_now`-> pins datetime.utcnow() to 2026-01-01T00:00:00Z

# Need a different state? Parametrize an existing fixture; don't create a new DB.

Few-Shot Examples Beat Vague Rules

Prose alone leaves ambiguity. Add 2 to 4 targeted examples of a canonical test and the model generalizes the pattern, it does not merely copy it. Few-shot examples are the strongest lever for consistency, edge cases, and output format.

Show one complete, idiomatic test that uses your real fixtures. New tests will mirror its structure, naming, and assertion style.

# ./standards/testing-style.md  (a canonical example to generalize from)

def test_transfer_rejects_when_balance_too_low(db, user):
    account = make_account(db, owner=user, balance=50)
    with pytest.raises(InsufficientFunds):
        transfer(db, account, amount=100)
    assert account.balance == 50          # state unchanged on failure
# ^ Note: AAA layout, real `db`/`user` fixtures, asserts the contract.

Write Explicit Criteria, Not Vague Wishes

"Write good tests" is a vague wish. Explicit criteria produce reliable output. Compare "be thorough" with "cover the happy path, one boundary value, and one error path; never test private methods directly."

Concrete, checkable rules remove the guesswork that makes generated tests inconsistent across files and contributors.

# In CLAUDE.md or the generation prompt -- explicit and checkable:
- Each public function gets: 1 happy-path, 1 edge/boundary, 1 failure test
- A test may fail for exactly ONE reason; split otherwise
- Mock ONLY at process boundaries (network, clock, filesystem)
- Forbidden: sleeping on real time, hitting a live service, asserting log text

Encapsulate Generation as a Skill

Make the workflow repeatable with a .claude/skills/ skill (project scope is shared via VCS; user scope is personal). The skill bundles your standard and can restrict tools and isolate output.

Use context: fork to isolate verbose generation output, allowed-tools to restrict what it can touch, and argument-hint to guide the caller. Now "generate tests to standard" is one reusable command instead of a re-typed paragraph.

# .claude/skills/gen-tests/SKILL.md
---
name: gen-tests
description: Generate tests for a module using project fixtures + style
context: fork
allowed-tools: [Read, Glob, Grep, Write]
argument-hint: <path/to/module.py>
---
Follow @./standards/testing-style.md and @./standards/fixtures.md.
Find siblings with Glob **/*test*, reuse existing fixtures, then Write the test file.

Find Patterns Before Generating

Don't generate in a vacuum. Have Claude follow the incremental investigation pattern first: Glob for existing test files, Read a couple, Grep for how a fixture is used, then write a new test that matches what's already there.

Grounding generation in the real codebase beats reciting a style guide, because the model copies living, working conventions instead of guessing.

# Glob to discover the established test layout
claude -p "Glob tests/**/*.py, Read two existing tests, \
Grep for usages of the `client` fixture, then write tests/test_orders.py \
following the same fixtures and naming. Do not invent new fixtures."

Generate Headless, Review Fresh in CI

In a pipeline, generate tests headless with -p (required: no human is present) and --output-format json so a later step can parse the result. Then review the generated tests in a separate, isolated session.

Fresh-instance review beats same-session self-review: the author retains its own reasoning and won't challenge its own tests. A clean reviewer catches tautological assertions and missing failure cases the generator overlooked.

# 1) Generate (headless, parseable)
claude -p "$(cat .ci/gen-tests-prompt.md)" --output-format json > gen.json

# 2) Review in a FRESH session, not the generation context
claude -p "Review the new tests in gen.json against ./standards/testing-style.md. \
Flag tautological asserts and any missing failure-path test." \
  --output-format json > review.json

Validate Structure, Then Retry with Feedback

When you ask for tests as structured output (tool_use + JSON Schema), validate the result. If it is malformed, use retry-with-feedback: resend the original request, the wrong output, and the exact validation error. This reliably fixes format and structural mistakes.

Two cautions from the fact sheet: retry does NOT help when the needed info is simply absent from the source, and you should mark a schema field required only if it is always present, or the model will fabricate it.

# Schema for emitted test cases -- 'edge_case' is optional, so NOT required
{
  "type": "object",
  "properties": {
    "test_name":   {"type": "string"},
    "fixtures":    {"type": "array", "items": {"type": "string"}},
    "assertion":   {"type": "string"},
    "edge_case":   {"type": "string"}
  },
  "required": ["test_name", "fixtures", "assertion"]
}
# On a validation failure: resend original + bad output + the exact error.

Quick Check

Apply the lesson to a realistic standards decision.

Recap: Test Generation & Standards

Key takeaways:

  • Put testing standards in project scope (./CLAUDE.md, .claude/rules/ with paths), shared via VCS; never depend on personal ~/.claude/CLAUDE.md in CI.
  • Modularize with @path imports; rules with frontmatter paths load only when editing matching files, saving context.
  • Document fixtures as the source of truth (purpose, shape, when to use) so the model reuses them instead of inventing stubs.
  • Few-shot (2-4 canonical examples) plus explicit criteria beat vague instructions; the model generalizes the pattern.
  • Wrap it in a .claude/skills/ skill; have Claude investigate existing tests (Glob/Read/Grep) before writing.
  • In CI, generate headless with -p --output-format json, then review in a fresh, isolated session.
  • Validate structured output; retry-with-feedback fixes format errors but not missing information, and require a schema field only if it is always present.

자주 묻는 질문

“테스트 생성 및 표준” 강의는 무료인가요?

네 — “테스트 생성 및 표준” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Claude Architect 강의 전체를 잠금 해제할 수 있습니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.

“테스트 생성 및 표준”에서 뭘 배우나요?

생성되는 테스트의 품질을 높이도록 픽스처와 표준을 문서화합니다 브라우저에서 직접 실행하는 실습 코드로 Claude Architect을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Claude Architect을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Claude Architect은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“테스트 생성 및 표준” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Claude Architect 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Claude Architect 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 비대화형 모드
  2. 구조화된 출력
  3. 검토를 위한 세션 격리
  4. 테스트 생성 및 표준
← Claude Architect(으)로 돌아가기