---
title: İddialar
source: 'https://academia.sh/tr/kurslar/birim-testi/iddialar'
course: 'Birim Testi ve Test Odaklı Geliştirme'
language: tr
updated: '2026-08-17T18:10:54+00:00'
license: 'CC BY-SA 4.0'
---

# İddialar

Eşitlik ile derin eşitliğin ayrımı, bir iddianın yakaladığı bozulma sayısıyla ölçülen sinyal gücü, kısmi eşleştirmenin gereksiz bağı kesmesi ve hata beklentisinin eşleştirmeyle daraltılması.

Önceki ders tek bir iddia kullandı: iki sayının eşitliği. Sınanan işlev bir sayı
döndürdüğü için bu yeterliydi. Ödünç verme işlemi ise bir sayı değil, bir kayıt döndürür:
üye numarası, kitap numarası, alış günü, son gün ve durum. Aynı iddia bu kayıtta bambaşka
davranır ve testin ne kadarını sınadığı, seçilen iddianın biçimine göre değişir.

Bu dersin sorusu iki katmanlıdır. Birincisi biçimseldir: hangi iddia hangi değer türü için
doğru araçtır? İkincisi ölçülebilirdir: bir iddia, sınadığı kodun kaç farklı bozulmasını
yakalar? İkinci soru birincisini kesin hâle getirir, çünkü "iyi iddia" sezgisel bir yargı
olmaktan çıkıp sayılabilir bir niceliğe dönüşür.

## Eşitlik ve Derin Eşitlik

Sınanacak işlev, ödünç kaydını üreten `oduncVer` işlevidir. Üye türü ödünç süresini ve
açıktaki en çok ödünç sayısını belirler; sınır aşıldığında işlem reddedilir.

```js
// odunc.mjs — odunc kaydi ureten islev
export const KURALLAR = {
  ogrenci: { oduncGun: 28, enCokOdunc: 10 },
  uye: { oduncGun: 14, enCokOdunc: 5 },
};

export function oduncVer(uye, kitapNo, gun) {
  const kural = KURALLAR[uye.tur];
  if (kural === undefined) throw new Error(`bilinmeyen uye turu: ${uye.tur}`);
  if (uye.aciktakiOdunc >= kural.enCokOdunc) {
    throw new Error(`odunc siniri asildi: ${kural.enCokOdunc}`);
  }
  return {
    uyeNo: uye.no,
    kitapNo,
    alisGunu: gun,
    sonGun: gun + kural.oduncGun,
    durum: 'odunc',
  };
}
```

Aynı beklentiyi iki iddia biçimiyle yazmak farkı görünür kılar.

```js
// esitlik.test.mjs — nesne donduren islevde esitlik ve derin esitlik
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { oduncVer } from './odunc.mjs';

const UYE = { no: 'U-17', tur: 'ogrenci', aciktakiOdunc: 2 };

test('esitlik nesneyi kimlikle karsilastirir', () => {
  const kayit = oduncVer(UYE, 'K-903', 1000);

  assert.equal(kayit, {
    uyeNo: 'U-17', kitapNo: 'K-903', alisGunu: 1000, sonGun: 1028, durum: 'odunc',
  });
});

test('derin esitlik yapiyi karsilastirir', () => {
  const kayit = oduncVer(UYE, 'K-903', 1000);

  assert.deepEqual(kayit, {
    uyeNo: 'U-17', kitapNo: 'K-903', alisGunu: 1000, sonGun: 1028, durum: 'odunc',
  });
});
```

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

```
not ok 1 - esitlik nesneyi kimlikle karsilastirir
ok 2 - derin esitlik yapiyi karsilastirir
# tests 2
# pass 1
# fail 1
```

Katı eşitlik iddiası nesneleri **kimlik** üzerinden karşılaştırır: iki ayrı nesne, alanları
birebir aynı olsa da eşit sayılmaz. Derin eşitlik ise yapıyı dolaşır ve karşılık gelen
alanları karşılaştırır. Kural yalındır: sayı, dizgi ve mantıksal değer için eşitlik; nesne,
dizi ve iç içe yapı için derin eşitlik.

## İddianın Sinyal Gücü

Bir iddianın değeri, geçtiğinde değil **düştüğünde** ortaya çıkar. Ölçüsü şudur: sınanan
kodun kaç farklı bozulmasını yakalar? Bu soru sayısal olarak yanıtlanabilir. Aşağıdaki
betik doğru kaydın beş ayrı bozulmuş sürümünü üretir ve üç iddia biçimini her birine
uygular.

```js
// iddia-gucu.mjs — uc iddia bicimi bes bozulmus gerceklestirimde denenir
import assert from 'node:assert/strict';
import { oduncVer } from './odunc.mjs';

const UYE = { no: 'U-17', tur: 'ogrenci', aciktakiOdunc: 2 };
const dogru = () => oduncVer(UYE, 'K-903', 1000);

const BOZUKLAR = {
  'sure-sabitlendi': () => ({ ...dogru(), sonGun: 1014 }),
  'durum-yanlis': () => ({ ...dogru(), durum: 'rezerve' }),
  'gun-kaydi': () => ({ ...dogru(), alisGunu: 1001 }),
  'kitap-dustu': () => { const k = dogru(); delete k.kitapNo; return k; },
  'uye-dustu': () => ({ ...dogru(), uyeNo: null }),
};

const BEKLENEN = {
  uyeNo: 'U-17', kitapNo: 'K-903', alisGunu: 1000, sonGun: 1028, durum: 'odunc',
};

const IDDIALAR = {
  'ok(kayit)': (k) => assert.ok(k),
  'equal(kayit.sonGun)': (k) => assert.equal(k.sonGun, 1028),
  'deepEqual(kayit)': (k) => assert.deepEqual(k, BEKLENEN),
};

for (const [iddiaAdi, iddia] of Object.entries(IDDIALAR)) {
  const yakalanan = [];
  for (const [bozukAd, bozuk] of Object.entries(BOZUKLAR)) {
    try {
      iddia(bozuk());
    } catch {
      yakalanan.push(bozukAd);
    }
  }
  const sayi = `${yakalanan.length}/${Object.keys(BOZUKLAR).length}`;
  console.log(`${iddiaAdi.padEnd(21)} ${sayi}  ${yakalanan.join(', ') || 'yok'}`);
}
```

```
ok(kayit)             0/5  yok
equal(kayit.sonGun)   1/5  sure-sabitlendi
deepEqual(kayit)      5/5  sure-sabitlendi, durum-yanlis, gun-kaydi, kitap-dustu, uye-dustu
```

Birinci satır aşırı geniş iddianın maliyetini gösterir. `assert.ok(kayit)` yalnız "bir
nesne döndü" der; kaydın içeriği ne olursa olsun yeşil kalır. Böyle bir test koşum
listesinde yer kaplar, süre harcar ve hiçbir bozulmayı bildirmez. Kalite ve Test Temelleri
kursunda tanıtılan yanlış alarm kavramının aynası budur: burada sinyal yanlış değil,
**yok**.

İkinci satır dar bir iddianın dürüst sınırını gösterir: tek alan sınandığında yalnız o
alanın bozulması yakalanır. Bu bir kusur değildir; testin adı da tek alanı söylüyorsa
beklenen davranış budur.

Üçüncü satır tam kapsamayı verir. Ama bu ölçüm tek yönlüdür: yakalanan bozulma sayısı
arttıkça testin **kırılganlık** riski de artar. Sonraki bölüm bu bedeli gösterir.

## Kısmi Eşleştirme

Kayda, işlemi izlemeye yarayan bir işlem numarası eklendiği varsayılsın. Davranış
kurallarının hiçbiri değişmez; yalnız kayıtta yeni bir alan vardır.

```js
// odunc.mjs — surum 2: kayda islem numarasi eklendi
export const KURALLAR = {
  ogrenci: { oduncGun: 28, enCokOdunc: 10 },
  uye: { oduncGun: 14, enCokOdunc: 5 },
};

let sayac = 0;

export function oduncVer(uye, kitapNo, gun) {
  const kural = KURALLAR[uye.tur];
  if (kural === undefined) throw new Error(`bilinmeyen uye turu: ${uye.tur}`);
  if (uye.aciktakiOdunc >= kural.enCokOdunc) {
    throw new Error(`odunc siniri asildi: ${kural.enCokOdunc}`);
  }
  sayac += 1;
  return {
    islemNo: `I-${String(sayac).padStart(4, '0')}`,
    uyeNo: uye.no,
    kitapNo,
    alisGunu: gun,
    sonGun: gun + kural.oduncGun,
    durum: 'odunc',
  };
}
```

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

```
not ok 1 - esitlik nesneyi kimlikle karsilastirir
not ok 2 - derin esitlik yapiyi karsilastirir
# tests 2
# pass 0
# fail 2
```

Derin eşitlik iddiası düştü, çünkü tam eşleşme **tam** demektir: kayıtta beklenmedik bir
alan bulunması da uyuşmazlıktır. Oysa sınanan kural — öğrenci ödüncünün yirmi sekiz gün
sürmesi — değişmedi. Test, ilgilenmediği bir alana bağlandığı için düştü.

Çözüm iddiayı zayıflatmak değil, **daraltmaktır**: beklenen alanların varlığı ve değeri
sınanır, geri kalanı serbest bırakılır.

```js
// kismi.test.mjs — beklenen alanlarin varligini sinayan kismi eslestirme
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { oduncVer } from './odunc.mjs';

function icerir(gercek, beklenen, yol = 'kayit') {
  for (const [alan, deger] of Object.entries(beklenen)) {
    const altYol = `${yol}.${alan}`;
    assert.ok(alan in gercek, `${altYol} alani yok`);
    if (deger !== null && typeof deger === 'object') icerir(gercek[alan], deger, altYol);
    else assert.equal(gercek[alan], deger, `${altYol} uyusmuyor`);
  }
}

const UYE = { no: 'U-17', tur: 'ogrenci', aciktakiOdunc: 2 };

test('ogrenci oduncunun son gunu yirmi sekiz gun sonradir', () => {
  const kayit = oduncVer(UYE, 'K-903', 1000);

  icerir(kayit, { uyeNo: 'U-17', kitapNo: 'K-903', sonGun: 1028, durum: 'odunc' });
});

test('kismi eslestirme yanlis alani gosterir', () => {
  const kayit = oduncVer(UYE, 'K-903', 1000);

  assert.throws(() => icerir(kayit, { sonGun: 1014 }), /kayit.sonGun uyusmuyor/);
});
```

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

```
ok 1 - ogrenci oduncunun son gunu yirmi sekiz gun sonradir
ok 2 - kismi eslestirme yanlis alani gosterir
# tests 2
# pass 2
# fail 0
```

`icerir` yardımcısı beklenen nesnenin alanlarını dolaşır, eksik alanı ve uyuşmayan değeri
ayrı iletilerle bildirir. İkinci test bu yardımcının kendisini sınar: yanlış bir beklenti
verildiğinde hangi alanın uyuşmadığını ileti içinde söylemelidir. Yardımcıyı sınamak
gereksiz görünebilir, ama bir iddia yardımcısı sessizce geçerse ona bağlı bütün testler
sinyalini yitirir.

Kısmi eşleştirmenin dozu bir seçimdir: fazla gevşek bırakılırsa `assert.ok` kadar zayıf,
fazla sıkı tutulursa tam derin eşitlik kadar bağlı olur. Ölçüt şudur: iddiada geçen her
alan, testin adında geçen kuralın parçası olmalıdır.

## Hata Bekleme

Kural ihlali durumunda işlemin reddedilmesi de bir davranıştır ve sınanması gerekir. Hata
bekleyen iddianın eşleştirmesiz biçimi ise sık rastlanan bir yanlış alarm kaynağıdır.

```js
// hata.test.mjs — esletirmesiz ve esletirmeli hata beklentisi
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { oduncVer } from './odunc.mjs';

const SINIRDAKI = { no: 'U-17', aciktakiOdunc: 10 };

test('esletirmesiz beklenti: sinir asiminda hata verir', () => {
  assert.throws(() => oduncVer(SINIRDAKI, 'K-903', 1000));
});

test('esletirmeli beklenti: sinir asiminda hata verir', () => {
  assert.throws(() => oduncVer(SINIRDAKI, 'K-903', 1000), /odunc siniri asildi: 10/);
});
```

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

```
ok 1 - esletirmesiz beklenti: sinir asiminda hata verir
not ok 2 - esletirmeli beklenti: sinir asiminda hata verir
# tests 2
# pass 1
# fail 1
```

Aynı çağrı, aynı düzenek, iki farklı sonuç. Gerçekte fırlatılan hataya bakmak ayrımı
açıklar.

```js
// firlatilan.mjs — testin gercekte yakaladigi hata
import { oduncVer } from './odunc.mjs';

const SINIRDAKI = { no: 'U-17', aciktakiOdunc: 10 };
try {
  oduncVer(SINIRDAKI, 'K-903', 1000);
} catch (hata) {
  console.log(`${hata.constructor.name}: ${hata.message}`);
}
```

```
Error: bilinmeyen uye turu: undefined
```

Düzenekteki üye nesnesinde `tur` alanı unutulmuş. İşlev ödünç sınırına hiç bakmadan, daha
önceki denetimde başka bir hata fırlatıyor. Eşleştirmesiz beklenti "herhangi bir hata"
gördüğü için yeşil kaldı ve sınamak istediği kural hiç çalışmadı. Eşleştirmeli beklenti
ise düşerek düzeneğin bozuk olduğunu bildirdi.

Bu, iddia seçiminin en pahalı hatasıdır: yeşil bir test, sınadığını sandığı kuralı hiç
çalıştırmamış olabilir. Hata beklentisi her zaman bir ölçüte bağlanmalıdır — hata sınıfı,
ileti örüntüsü ya da hata nesnesinin bir alanı.

## Özet

- Katı eşitlik nesneleri kimlikle karşılaştırır; nesne ve dizi döndüren işlevlerde derin
  eşitlik ya da kısmi eşleştirme gerekir.
- Bir iddianın sinyal gücü, sınanan kodun kaç bozulmasını yakaladığıyla ölçülür; ölçümde
  `assert.ok(kayit)` beş bozulmanın hiçbirini, derin eşitlik beşini de yakaladı.
- Tam derin eşitlik davranışla ilgisiz alanlara da bağlanır; kayda yeni bir alan eklendiğinde
  kural değişmediği hâlde test düştü.
- Kısmi eşleştirme beklenen alanları sınar, geri kalanını serbest bırakır; iddiada geçen her
  alan testin adında geçen kuralın parçası olmalıdır.
- Eşleştirmesiz hata beklentisi yanlış hatayı da kabul eder ve sınamak istediği kural hiç
  çalışmadan yeşil kalabilir.

## Sonraki Adım

Bu derste iddiaların ne söylediği ölçüldü, ama testlerin adları sessizce arka planda kaldı.
Oysa düşen bir koşumun ilk verdiği bilgi iddia değil, **addır**: `not ok 2` satırının
yanındaki cümle. O cümle "kayit dogru" gibi bir şey söylüyorsa okuyanın kaynağa gitmesi
gerekir; kuralı söylüyorsa çoğu zaman gerekmez. Sonraki ders test adlandırmasını ele alır
ve bir test kümesinin adlarını okunabilir bir kural listesine dönüştürür.
