# Test Writing, TDD, and Coverage Strategies

> Source: https://sukruyusufkaya.com/en/learn/claude-ustaligi/test-yazma
> Updated: 2026-05-11T13:48:32.890Z
> Category: Claude Ustalığı
> Module: 4. Coding with Claude
**TLDR:** Workflow for writing tests with Claude: unit, integration, property-based, snapshot. Coverage targets and which tests not to write.

# Test Piramidi (Hâlâ) Doğru

```
       ▲
      ▲ ▲      e2e (~5%)
     ▲   ▲     entegrasyon (~25%)
    ▲     ▲    birim (~70%)
   ▲       ▲
   ─────────
```

Claude'a test yazdırmadan önce hangi seviyede test gerektiğini sen belirle.

### Birim test

Tek bir fonksiyonun **saf davranışını** test eder. Dış efekt yok. Hızlı çalışır.

```python
def test_normalize_phone_tr_format():
    assert normalize_phone("+90 (555) 123-45-67") == "+90 555 123 45 67"
```

İdeal kapsama: %70-90 satır kapsama.

### Entegrasyon

Birden fazla bileşen bir arada test edilir: gerçek DB (test DB), gerçek HTTP, gerçek dosya sistemi.

Yavaştır ama yüksek değerlidir. Modül 11'deki RAG dersinde kullanacağız.

### Property-based

Claude'un parlayacağı yer: invariant ifade et, çerçeve binlerce rastgele girdi üretir.

```python
from hypothesis import given, strategies as st

@given(st.text())
def test_normalize_idempotent(s):
    once  = normalize_phone(s)
    twice = normalize_phone(once or "")
    if once is not None:
        assert twice == once
```

### Snapshot

LLM çıktıları, render edilmiş bileşenler ya da büyük JSON cevabı için. Snapshot diff'i izlenir.

Anti-pattern: snapshot'u kararlı tutmadan yenilemek; snapshot'ı 'yeşil yap' diye otomatik onaylamak.

## Claude'a Test Yazdırma Şablonu

```text
<role>Kıdemli test mühendisi.</role>

<framework>pytest + hypothesis</framework>

<unit_under_test>
{{kaynak_kod}}
</unit_under_test>

<spec>
{{davranış_kuralları}}
</spec>

<task>
- 6-10 birim test üret.
- Mutlaka happy path + 3 edge + 1 hata yolu.
- Hypothesis ile en az 1 property-based test ekle.
- Test isimleri: test_<function>_<senaryo>.
</task>

<output_format>
- Tek dosya, modüler
- Pytest fixture'ları kullan
- Yorumda her testin amacı tek satırda
</output_format>
```

> **Coverage tek başına yalan söyler**
>
> %100 satır kapsama, davranışın doğru olduğunu göstermez. Ne testi yazıldığı kadar **hangi davranışın test edildiği** önemlidir. Snapshot ile şişen kapsama ölçütlerine kanma.

```python
# Hızlı pytest mock setup — gerçek pytest'i ayrı çalıştırırsın
def normalize_phone(raw, default_country="TR"):
    import re
    if not raw or not isinstance(raw, str): return None
    digits = re.sub(r"[^0-9]", "", raw)
    if len(digits) == 10 and digits.startswith("5"): digits = "90" + digits
    elif len(digits) == 11 and digits.startswith("0"): digits = "90" + digits[1:]
    elif len(digits) == 12 and digits.startswith("90"): pass
    else: return None
    return f"+{digits[:2]} {digits[2:5]} {digits[5:8]} {digits[8:10]} {digits[10:]}"

# 6 mini-test
ASSERTIONS = [
    ("+90 (555) 123-45-67", "+90 555 123 45 67"),
    ("905551234567",        "+90 555 123 45 67"),
    ("05551234567",         "+90 555 123 45 67"),
    ("",                    None),
    ("hello",               None),
    (None,                  None),
]
for inp, exp in ASSERTIONS:
    got = normalize_phone(inp)
    print(f"{str(inp)!r:25} → {got!r:25} {'✅' if got == exp else '❌'}")
```

**Boşluk doldurma egzersizi (text):**
```text
Test piramidinde tabanı _____ , ortası _____ , tepesi _____ testlerdir. Property-based testler _____ ifade eder ve çerçeve rastgele girdi üretir.
```

> ✋ Kontrol noktası: `q-404-mc1`