---
title: 'Hata Yaşam Döngüsü'
source: 'https://academia.sh/tr/kurslar/test-temelleri/hata-yasam-dongusu'
course: 'Kalite ve Test Temelleri'
language: tr
updated: '2026-08-17T18:10:53+00:00'
license: 'CC BY-SA 4.0'
---

# Hata Yaşam Döngüsü

Hata, kusur ve arıza ayrımı, hata kaydının alanları, önem ile önceliğin ayrılması ve kaydın yaşam döngüsünün durum makinesi olarak modellenip geçiş kapsamının ölçülmesi.

Bir kâhin sapma gösterdiğinde iş bitmez, başlar. Sapmanın kaydedilmesi, tekrarlanabilir
biçimde anlatılması, önceliklendirilmesi, giderilmesi ve giderildiğinin doğrulanması
gerekir. Bu adımların her biri bir durumdur ve aralarında yalnız belirli geçişler
geçerlidir.

Bu ders o döngüyü kurar. Döngünün kendisi de bir sistemdir ve önceki derslerdeki
tekniklerle sınanabilir; son bölümde bu yapılır.

## Hata, Kusur ve Arıza

Türkçede de İngilizcede de birbirinin yerine kullanılan üç terim ayrı şeyleri adlandırır.

**Hata** (error) insanın yaptığı yanlıştır: kuralın yanlış anlaşılması, bir sınırın yanlış
okunması, bir operatörün yanlış yazılması. Hata bir üründe değil, bir kişide olur.

**Kusur** (defect) hatanın üründe bıraktığı izdir: yanlış yazılmış koşul, eksik denetim,
yanlış belirtim maddesi. Kusur üründe durur ve kimse çalıştırmasa da oradadır.

**Arıza** (failure) kusurun dışa vurmasıdır: programın gözlenen davranışının beklenenden
sapması. Her kusur arızaya dönüşmez — kusurun bulunduğu dal hiç çalışmıyorsa arıza görünmez.

Ayrım pratikte işe yarar. Bir hata kaydı arızayı anlatır, çünkü gözlenen budur. Düzeltme
kusuru hedefler. Kusurun tekrarlanmaması için yapılan iş ise hataya bakar: aynı yanlış
anlama başka yerlerde de var mı?

## Hata Kaydının Alanları

İyi bir hata kaydının ölçütü tektir: kaydı okuyan başka bir kişi, yazarına hiç soru sormadan
arızayı yeniden üretebilmelidir.

Kayıt şu alanları taşır. **Kimlik** ve **başlık**: başlık arızayı tek cümlede söyler, gerekçe
değil gözlem içerir. **Ortam**: sürüm, yapılandırma, veri kümesi — arızanın yeniden
üretilebilmesi için gereken bağlam. **Ön koşul ve adımlar**: senaryo yazımı dersindeki
biçimin aynısı. **Gözlenen sonuç** ve **beklenen sonuç**: ikisi ayrı ayrı yazılır, çünkü
farkı okuyan kişi görmelidir. **Kanıt**: günlük kaydı, çıktı, ekran görüntüsü.
**İzlenebilirlik bağı**: hangi kural, hangi senaryo, hangi sürüm.

En sık atlanan alan beklenen sonuçtur. "Ücret yanlış hesaplanıyor" cümlesi bir kayıt değil,
bir şikâyettir; kayıt "gün=0, öğrenci, şube dışı iade için 3 birim hesaplandı, kural gereği 2
birim olmalıydı" der.

## Önem ve Öncelik

İki alan sık sık karıştırılır ve karıştırıldığında yanlış iş sırası doğar.

**Önem** (severity) arızanın etkisinin büyüklüğüdür: veri kaybı mı, yanlış tutar mı, yerleşim
bozukluğu mu? Ürünün kendisine bakılarak belirlenir ve büyük ölçüde nesneldir.

**Öncelik** (priority) düzeltmenin ne zaman yapılacağıdır. Etkiye ek olarak kaç kullanıcıyı
etkilediğine, kaçınma yolu olup olmadığına, sürüm takvimine ve düzeltmenin riskine bakar.

İkisi bağımsızdır. Yılda bir çalışan bir raporda veri kaybı yüksek önemli, düşük öncelikli
olabilir. Açılış ekranındaki bir yazım yanlışı düşük önemli, yüksek öncelikli olabilir.
İki alanı tek alana indiren bir kayıt biçimi, bu iki kararı birbirine karıştırmaya zorlar.

## Yaşam Döngüsü Bir Durum Makinesidir

Kaydın izlediği yol serbest değildir. Doğrulanmamış bir kayıt kapatılamaz, kapatılmış bir
kayda düzeltme iliştirilemez. Bu kısıtlar bir durum makinesidir.

```js
// dongu.mjs — hata kaydinin durum makinesi
export const GECISLER = {
  yeni: { ata: 'atandi', reddet: 'reddedildi' },
  atandi: { duzelt: 'duzeltildi', reddet: 'reddedildi' },
  duzeltildi: { dogrula: 'dogrulandi', yenidenAc: 'yenidenAcildi' },
  dogrulandi: { kapat: 'kapandi' },
  kapandi: { yenidenAc: 'yenidenAcildi' },
  reddedildi: { yenidenAc: 'yenidenAcildi' },
  yenidenAcildi: { ata: 'atandi' },
};

export const DURUMLAR = Object.keys(GECISLER);
export const OLAYLAR = ['ata', 'duzelt', 'dogrula', 'kapat', 'reddet', 'yenidenAc'];

export function uygula(durum, olay) {
  const sonraki = GECISLER[durum]?.[olay];
  if (sonraki === undefined) throw new Error(`gecersiz gecis: ${durum} + ${olay}`);
  return sonraki;
}
```

Makine yazılı olduğunda geçerli ve geçersiz geçişler sayılabilir.

```js
// sayim.mjs — butun durum-olay ciftlerinin sayilmasi
import { DURUMLAR, OLAYLAR, GECISLER, uygula } from './dongu.mjs';

let gecerli = 0;
let reddedilen = 0;
for (const durum of DURUMLAR) {
  for (const olay of OLAYLAR) {
    if (GECISLER[durum][olay] !== undefined) { gecerli += 1; continue; }
    try { uygula(durum, olay); } catch { reddedilen += 1; }
  }
}

const toplam = DURUMLAR.length * OLAYLAR.length;
console.log(`durum sayisi  : ${DURUMLAR.length}`);
console.log(`olay sayisi   : ${OLAYLAR.length}`);
console.log(`tum ciftler   : ${toplam}`);
console.log(`gecerli gecis : ${gecerli}`);
console.log(`gecersiz cift : ${toplam - gecerli}, reddedilen: ${reddedilen}`);
```

```
durum sayisi  : 7
olay sayisi   : 6
tum ciftler   : 42
gecerli gecis : 10
gecersiz cift : 32, reddedilen: 32
```

Kırk iki çiftin yalnız onu geçerlidir; geri kalan otuz ikisi reddedilmelidir ve reddedilmiştir.
Bu ikinci sayı çoğu zaman gözden kaçar. Kaydın "doğrulandı" durumuna gelmeden kapatılabilmesi
bir kusurdur, ama hiçbir mutlu yol senaryosu bunu göstermez.

**Doğrulandı** durumunun ayrı bir adım olması da bilinçlidir. Düzeltmeyi yapan kişi kaydı
kapatamaz; kapatma yetkisi arızayı bildiren ya da doğrulayan taraftadır. Yeniden test bu
adımda koşturulur.

## Durum Geçiş Testi

Dördüncü derste ertelenen teknik burada uygulanır. **Durum geçiş testi** (state transition
testing) denenmesi gereken şeyin değerler değil geçişler olduğu durumlarda kullanılır ve
ölçüsü **geçiş kapsamıdır**: geçerli geçişlerin kaçı en az bir kez denendi?

```js
// gecis-kapsami.mjs — iki senaryo kumesinin gecis kapsami
import { GECISLER, uygula } from './dongu.mjs';

const TUM_GECISLER = Object.entries(GECISLER)
  .flatMap(([durum, olaylar]) => Object.keys(olaylar).map((olay) => `${durum}+${olay}`));

function kapsam(yollar) {
  const gorulen = new Set();
  for (const yol of yollar) {
    let durum = 'yeni';
    for (const olay of yol) {
      gorulen.add(`${durum}+${olay}`);
      durum = uygula(durum, olay);
    }
  }
  return gorulen;
}

const MUTLU_YOL = [['ata', 'duzelt', 'dogrula', 'kapat']];
const GENIS_KUME = [
  ['ata', 'duzelt', 'dogrula', 'kapat', 'yenidenAc', 'ata'],
  ['ata', 'duzelt', 'yenidenAc', 'ata'],
  ['reddet', 'yenidenAc', 'ata', 'reddet'],
];

for (const [ad, yollar] of [['mutlu yol', MUTLU_YOL], ['genis kume', GENIS_KUME]]) {
  const gorulen = kapsam(yollar);
  const eksik = TUM_GECISLER.filter((g) => !gorulen.has(g));
  console.log(`${ad.padEnd(10)}: ${gorulen.size}/${TUM_GECISLER.length} gecis denendi`);
  if (eksik.length) console.log(`  denenmeyen: ${eksik.join(', ')}`);
}
```

```
mutlu yol : 4/10 gecis denendi
  denenmeyen: yeni+reddet, atandi+reddet, duzeltildi+yenidenAc, kapandi+yenidenAc, reddedildi+yenidenAc, yenidenAcildi+ata
genis kume: 10/10 gecis denendi
```

Mutlu yol geçişlerin yüzde kırkını dener. Denenmeyen altı geçişin hepsi olağandışı akışlardır:
reddetme, yeniden açma, doğrulamanın başarısız olması. Bunlar gerçek kullanımda en çok tartışma
çıkaran akışlardır ve tam da bu yüzden en az sınananlardır.

Üç yol ekleyerek kapsam tamamlandı. Ölçüm, hangi yolların eklenmesi gerektiğini de söylüyordu —
eksik geçişlerin listesi doğrudan yazılacak senaryoların listesidir.

## Özet

- Hata insanın yaptığı yanlış, kusur onun üründe bıraktığı iz, arıza kusurun gözlenen dışa
  vurumudur; her kusur arızaya dönüşmez.
- Hata kaydının ölçütü, okuyan başka bir kişinin arızayı soru sormadan yeniden
  üretebilmesidir; gözlenen ve beklenen sonuç ayrı ayrı yazılır.
- Önem arızanın etkisini, öncelik düzeltmenin ne zaman yapılacağını söyler; ikisi bağımsızdır
  ve tek alana indirildiğinde kararlar karışır.
- Yaşam döngüsü bir durum makinesidir; örnekte kırk iki durum-olay çiftinden onu geçerli,
  otuz ikisi reddedilmesi gerekendir.
- Durum geçiş testinin ölçüsü geçiş kapsamıdır; mutlu yol on geçişten dördünü denedi,
  denenmeyenlerin listesi yazılacak senaryoların listesini verdi.

## Kurs Kapanışı

Kurs iki soruyu yanıtladı. Birincisi testin **ne** olduğuydu. Kalite bir uygunluk yargısı
olarak tanımlandı; ürün kalitesiyle süreç kalitesi ayrıldı; doğrulama ile geçerleme
birbirinden koparıldı ve belirtimine tam uyan bir programın yine de yanlış olabileceği
gösterildi. İşlevsel olmayan beklentiler adlandırılıp ölçülebilir ölçütlere çevrildi. Testin
bir teknikler kümesi olmadan önce bir tutum olduğu, aynı koda bakan iki bakışın farklı şeyler
bulduğu ölçüldü. Teslimat modelinin testi ucuzlatmadığı, yalnız aynı sınamanın ne zaman
yapılacağını belirlediği gösterildi.

İkincisi **hangi** testin yazılacağıydı. Testler kapsadıkları sınıra, dayandıkları bilgiye ve
amaçlarına göre sınıflandırıldı. Girdi seçimi sezgiden çıkarılıp denklik sınıfları, sınır
değerleri ve karar tablosuyla gerekçelendirildi. Sınanacak şey bir senaryo biçimine
kavuşturuldu ve o biçimden çalıştırılabilir teste geçildi. Beklenen sonucun nereden geldiği
sorusu ayrı bir problem olarak ele alındı ve üç kâhin karşılaştırıldı. Son olarak bulunan
sapmanın kayıttan kapanışa giden yolu bir durum makinesi olarak kuruldu.

Yanıtlanmayan soru testin **nasıl** yazılacağıdır. Bir denetimin iç düzeni nedir; hazırlık,
uygulama ve doğrulama nasıl ayrılır? İddia ne söylemeli, ne söylememeli? Bir birim, dış
dünyaya dokunmadan nasıl sınanır — bağımlılıklar sahte bağımlılıklarla nasıl değiştirilir ve
hangi türü nerede kullanılır? Kapsam ölçümü ne söyler, hangi soruya yanıt vermez? Testi koddan
önce yazmak tasarımı nasıl değiştirir?

Sonraki kurs, **Birim Testi ve Test Odaklı Geliştirme**, bu soruları ele alır. Hızlı ve
bağımsız testlerin yazımı, iddiaların anlamlı kurulması, bağımlılıkların dışarıdan verilmesi,
sahte bağımlılıkların doğru türde kullanılması, satır ve dal kapsamının okunması ve
kırmızı–yeşil–yeniden düzenle döngüsü orada kurulur. Bu kursta seçilen testler, orada
yazılacak testlerdir.
