---
title: 'Kırmızı–Yeşil–Yeniden Düzenle'
source: 'https://academia.sh/tr/kurslar/birim-testi/kirmizi-yesil-yeniden-duzenle'
course: 'Birim Testi ve Test Odaklı Geliştirme'
language: tr
updated: '2026-08-17T18:10:54+00:00'
license: 'CC BY-SA 4.0'
---

# Kırmızı–Yeşil–Yeniden Düzenle

Testin koddan önce yazıldığı üç adımlı döngünün her adımının koşturularak gösterilmesi, sabit değerle geçilen yeşilin üçgenlemeyle genelleştirilmesi ve yeniden düzenleme adımının güvence koşulu.

Birim Test Pratiği konusunda her testte kod önce vardı: bir hata raporu, bir kural ya da bir
yeniden düzenleme, sınanacak bir gerçekleştirimi hazır buldu. Test o gerçekleştirimi
doğruladı, ölçtü ya da kırılganlığını gösterdi.

Bu konu sırayı tersine çevirir. Test önce yazıldığında artık bir doğrulama aracı değil, bir
**tasarım aracıdır**: hangi işlevin hangi imzayla var olacağını, hangi girdiyi alacağını ve
ne döndüreceğini test belirler. Bu tersine çevirmenin adı **test odaklı geliştirmedir** (test
driven development) ve üç adımlı bir döngüyle işler.

Kurulacak yeni kural ödünç yenilemesidir. Bir üye elindeki kitabın süresini uzatabilir;
yenilenen ödüncün son tarihi, yenileme gününden itibaren üye türünün ödünç süresi kadar
ileri alınır.

## Kırmızı: Henüz Olmayan Kodun Testi

Döngü, geçmeyen bir testle başlar. Testin çalışabilmesi için sınanan işlevin **var olması**
gerekir; bu yüzden ilk yazılan şey, yalnız derlenmeye yetecek kadar boş bir gerçekleştirimdir.

```js
// yenileme.mjs — surum 0: islev var, davranis yok
export function yenile(kayit, bugun) {
  return kayit;
}
```

Testin kendisi, henüz yazılmamış davranışı tarif eder.

```js
// yenileme.test.mjs — kirmizi adim: tek kural, henuz gerceklestirim yok
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { yenile } from './yenileme.mjs';

test('ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir', () => {
  const kayit = { uyeNo: 'U-17', uyeTuru: 'ogrenci', sonGun: 1028 };

  const yeni = yenile(kayit, 1020);

  assert.equal(yeni.sonGun, 1048);
});
```

```sh
node --test --test-reporter=tap yenileme.test.mjs | grep -E '^ *(ok|not ok|# (tests|pass|fail))'
```

```
not ok 1 - ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir
# tests 1
# pass 0
# fail 1
```

Bu adımda üç karar aynı anda verildi ve hiçbiri gerçekleştirim yazılırken verilmedi.
İşlevin adı `yenile`, girdileri ödünç kaydı ile gün numarası, çıktısı güncellenmiş bir
kayıt. Test odaklı geliştirmenin tasarım tarafı budur: arayüz, onu **kullanan** koddan
türer.

Kırmızı koşumun güvencesi birinci derste anılan şeydir: testin düşebildiği görüldü.
Yazıldığı anda yeşil olan bir test, yanlış bir şeyi sınıyor ya da hiçbir şeyi sınamıyor
olabilir; bu ihtimal ancak düşen bir koşum görülerek elenir.

## Yeşil: En Kısa Yol

İkinci adımın tek ölçütü testi geçirmektir. Doğru tasarım, genel çözüm ya da temiz kod bu
adımın hedefi değildir; onlar üçüncü adımın işidir.

```js
// yenileme.mjs — surum 1: testi gecirmenin en kisa yolu
export function yenile(kayit, bugun) {
  return { ...kayit, sonGun: 1048 };
}
```

```sh
node --test --test-reporter=tap yenileme.test.mjs | grep -E '^ *(ok|not ok|# (tests|pass|fail))'
```

```
ok 1 - ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir
# tests 1
# pass 1
# fail 0
```

Sabit değer döndüren bu sürüm açıkça yanlıştır ve kasıtlıdır. Yaptığı iş, testin gerçekten
o değeri sınadığını kanıtlamaktır: kırmızıdan yeşile geçişin nedeni yazılan satırdır,
başka bir şey değil.

Bu adım aynı zamanda bir teşhis aracıdır. Sabit değer yazıldığı hâlde test yeşile dönmüyorsa
sorun gerçekleştirimde değil, testin kendisindedir.

## Üçgenleme

Sabit değerin yanlışlığını kod değil, **ikinci bir örnek** ortaya çıkarır. Aynı kuralın
farklı bir girdiyle yazılmış hâli, gerçekleştirimi genelleşmeye zorlar. Bu tekniğe
**üçgenleme** (triangulation) denir.

```js
// yenileme.test.mjs — surum 2: ikinci uye turu eklendi
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { yenile } from './yenileme.mjs';

test('ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir', () => {
  const kayit = { uyeNo: 'U-17', uyeTuru: 'ogrenci', sonGun: 1028 };

  const yeni = yenile(kayit, 1020);

  assert.equal(yeni.sonGun, 1048);
});

test('standart uye oduncu yenilendiginde son tarih bugunden on dort gun sonradir', () => {
  const kayit = { uyeNo: 'U-42', uyeTuru: 'uye', sonGun: 1014 };

  const yeni = yenile(kayit, 1020);

  assert.equal(yeni.sonGun, 1034);
});
```

```sh
node --test --test-reporter=tap yenileme.test.mjs | grep -E '^ *(ok|not ok|# (tests|pass|fail))'
```

```
ok 1 - ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir
not ok 2 - standart uye oduncu yenilendiginde son tarih bugunden on dort gun sonradir
# tests 2
# pass 1
# fail 1
```

Döngü yeniden kırmızıya döndü ve bu sefer kırmızının işaret ettiği şey belirgin: sabit
değer yetmiyor. Genelleştirme artık bir tahmin değil, düşen testin dayattığı bir zorunluluk.

```js
// yenileme.mjs — surum 2: sabit deger yerine kural tablosu
export const KURALLAR = { ogrenci: { oduncGun: 28 }, uye: { oduncGun: 14 } };

export function yenile(kayit, bugun) {
  return { ...kayit, sonGun: bugun + KURALLAR[kayit.uyeTuru].oduncGun };
}
```

```sh
node --test --test-reporter=tap yenileme.test.mjs | grep -E '^ *(ok|not ok|# (tests|pass|fail))'
```

```
ok 1 - ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir
ok 2 - standart uye oduncu yenilendiginde son tarih bugunden on dort gun sonradir
# tests 2
# pass 2
# fail 0
```

## Yeniden Düzenle: Yeşilin Üzerinde Çalışmak

Üçüncü adımın tanımı kesindir: **yeniden düzenleme** (refactoring), dışarıdan gözlenen
davranışı değiştirmeden iç yapıyı iyileştirmektir. Yeni kural eklenmez, yeni durum
ele alınmaz, hata düzeltilmez. Yalnız yapı değişir.

```js
// yenileme.mjs — surum 3: sure hesabi adlandirilmis bir isleve alindi
export const KURALLAR = { ogrenci: { oduncGun: 28 }, uye: { oduncGun: 14 } };

export function oduncSuresi(uyeTuru) {
  return KURALLAR[uyeTuru].oduncGun;
}

export function yenile(kayit, bugun) {
  return { ...kayit, sonGun: bugun + oduncSuresi(kayit.uyeTuru) };
}
```

```sh
node --test --test-reporter=tap yenileme.test.mjs | grep -E '^ *(ok|not ok|# (tests|pass|fail))'
```

```
ok 1 - ogrenci oduncu yenilendiginde son tarih bugunden yirmi sekiz gun sonradir
ok 2 - standart uye oduncu yenilendiginde son tarih bugunden on dort gun sonradir
# tests 2
# pass 2
# fail 0
```

Bu adımı mümkün kılan şey, ondan önceki iki adımdır. Yeşil bir test kümesi olmadan yeniden
düzenleme bir yeniden yazımdır ve doğruluğu ancak gözle denetlenebilir. Testler yeşilken
yapılan her yapı değişikliği, koşumun kendisiyle doğrulanır.

Sekizinci dersteki ölçüm burada karşılığını bulur. Testler gerçekleştirime bağlıysa bu adım
kırmızıya döner ve yeniden düzenleme cezalandırılır. Testler davranışa bağlıysa üçüncü adım
serbesttir. Test odaklı geliştirme, testleri kullanan koddan türettiği için davranışa bağlı
test yazmayı kolaylaştırır — ama garanti etmez; sözleşme ile iç ayrıntı ayrımını yine yazan
kişi yapar.

## Üç Adımın Böldüğü Sorular

Döngünün değeri, adımlarının aynı anda düşünülmesi gereken üç soruyu birbirinden ayırmasıdır.

Kırmızı adımda tek soru şudur: **ne** istiyorum? Kural nedir, arayüz nasıl kullanılacak,
beklenen sonuç nedir? Gerçekleştirim hiç düşünülmez.

Yeşil adımda tek soru şudur: bu testi **nasıl** geçiririm? En kısa yol yeterlidir; tasarım
kaygısı bu adımda bir dikkat dağınıklığıdır.

Yeniden düzenleme adımında tek soru şudur: elde duran kod **nasıl daha iyi olur**? Bu
soruya verilen yanıtın doğru olup olmadığını testler bildirir.

Üç sorunun aynı anda düşünülmesi, sıradan bir programlama seansında sürekli yaşanan
şeydir ve maliyeti dikkat maliyetidir. Döngü bu maliyeti üçe bölerek düşürür.

## Özet

- Test odaklı geliştirmede test bir doğrulama aracı değil tasarım aracıdır: işlevin adı,
  girdileri ve çıktısı onu kullanan testten türer.
- Kırmızı adımın güvencesi testin düşebildiğinin görülmesidir; yazıldığı anda yeşil olan
  test yanlış bir şeyi sınıyor olabilir.
- Yeşil adımın tek ölçütü testi geçirmektir; sabit değer döndüren sürüm, geçişin nedeninin
  yazılan satır olduğunu kanıtlar.
- Üçgenleme, ikinci bir örnekle gerçekleştirimi genelleşmeye zorlar; genelleştirme bir
  tahmin değil düşen testin dayatmasıdır.
- Yeniden düzenleme davranışı değiştirmeden iç yapıyı iyileştirir ve ancak yeşil bir test
  kümesinin üzerinde güvenli olur.

## Sonraki Adım

Bu derste döngü iki kez döndü ve her turda tek bir kural ele alındı. Adım boyu bir seçimdir:
aynı iş üç kuralı birden kapsayan tek bir turla da yürütülebilirdi. O seçimin bedeli
ölçülebilir — düşen testin işaret ettiği yer, iki koşum arasında değişen satır sayısı ve
geri dönülecek son yeşil noktaya olan uzaklık. Sonraki ders aynı özelliği iki farklı adım
boyuyla kurar ve iki koşumu karşılaştırır.
