---
title: 'Altyapı Testi'
source: 'https://academia.sh/tr/kurslar/kod-olarak-altyapi/altyapi-testi'
course: 'Kod Olarak Altyapı'
language: tr
updated: '2026-08-17T18:09:07+00:00'
license: 'CC BY-SA 4.0'
---

# Altyapı Testi

Altyapı değişikliğinin üç seviyede doğrulanması: birim, sözleşme ve uçtan uca doğrulamanın aynı on beş kusurluk kümede koşturulması, her seviyenin tuttuğu, yalnız kendisinin tuttuğu, süresi, yarattığı kaynak ve kurgu birim cinsinden maliyeti, üç seviyenin de kaçırdığı ortak boşluğun adlandırılması ve temizlenmeyen test kaynaklarının bıraktığı artık ile sızan maliyetin sayılması.

Politika taraması kaydın **kabul edilebilirliğini** sınadı ve iki katmanda da kararsız kalan bir
kural bıraktı: değeri uygulama anında atanan bir alan. O kararsızlık tesadüf değil, sınırdır —
tarama kaydı okur, koşan altyapıyı görmez. Kaynak gerçekten açılıyor mu, diski bağlanıyor mu,
kuyruğa yazılan ileti veri deposuna ulaşıyor mu: bunların hiçbiri metinde yazmaz.

**Altyapı testi** bu soruları sorar ve yazılım tarafındaki test seviyeleriyle aynı adları taşır —
birim, sözleşme, uçtan uca — ama hizalama adlarda değil, **neyin yaratıldığındadır**: burada en üst
seviye gerçek kaynak açar, gerçek ücret işletir ve arkasında iz bırakır. Bu ders üç seviyeyi aynı
kusur kümesinde koşturur ve her biri için üç şey sayar: tuttuğu kusur, süresi ve maliyeti. Sonra
iki sayı daha gelir: üç seviyenin birden kaçırdığı ortak boşluk ve testin arkasında bıraktığı
temizlenmemiş kaynak. Through-line **bölgesel ölçüm ağıdır** ve kurgudur.

## Kusur Kümesi ve Üç Seviye

**AD13 — bilinen kusur kümesi on beş kusurdur, elle işaretlenmiştir ve her kusur bir katmana
bağlıdır**: `tanim` (tek kaynağın tanımında görünür), `iliski` (ancak iki kaynak karşılaştırılınca
görünür), `kosum` (ancak kaynak koşarken görünür), `degisim` (ancak var olan altyapı üzerine
uygulanınca görünür). **AD14 — birim doğrulaması tek kaynağın ya da modülün tanımını kaynak
yaratmadan sınar; sözleşme doğrulaması plan üzerinde koşar ve yalnız arayüz alanlarına bakar.**
**AD15 — uçtan uca doğrulama gerçek kaynak yaratır ama yalnız ana akışı koşturur; yan akışta kalan
kusur ona görünmez.**

```js
// seviye.mjs — ayni kusur kumesi uc dogrulama seviyesinde kosturulur (model)

// [kod, kusur, katman (nerede gorunur), alan, yol (uctan uca akisinda ana mi yan mi)]
const KUSUR = [
  ["D01", "makine diski 10 GB, toplayici yaziyor", "tanim", "disk_gb", "ana"],
  ["D02", "kuyruk saklamasi 0 saat", "tanim", "saklama", "yan"],
  ["D03", "arsiv sinifi sicak birakilmis", "tanim", "sinif", "yan"],
  ["D04", "toplayici boyutu kucuk", "tanim", "boyut", "ana"],
  ["D05", "sahip etiketi yazilmamis", "tanim", "sahip", "yan"],
  ["D06", "makine bolgesi ag bolgesiyle uyusmuyor", "iliski", "bolge", "ana"],
  ["D07", "kuyruk ile veri deposu ayri bolgede", "iliski", "bolge", "yan"],
  ["D08", "modul cikti adi tuketicinin bekledigi degil", "iliski", "cikti", "ana"],
  ["D09", "yedek penceresi bakim penceresiyle cakisiyor", "iliski", "pencere", "yan"],
  ["D10", "guvenlik kurali toplayici trafigini kesiyor", "kosum", "kural", "ana"],
  ["D11", "disk baglanmiyor, baglama noktasi yok", "kosum", "baglama", "ana"],
  ["D12", "kimlik yetkisi eksik, depoya yazilamiyor", "kosum", "yetki", "ana"],
  ["D13", "alan degisikligi kaynagi yeniden olusturuyor, veri gidiyor", "degisim", "disk_gb", "ana"],
  ["D14", "yerinde guncelleme sirasinda kesinti oluyor", "degisim", "boyut", "ana"],
  ["D15", "kayit disi elle degisikligin uzerine yaziliyor", "degisim", "kural", "ana"],
].map(([kod, ne, katman, alan, yol]) => ({ kod, ne, katman, alan, yol }));

// AD16: uctan uca dogrulama gercek kaynak yaratir; adet, yaratma suresi ve saatlik ucret kurgudur
const KAYNAK = [["ag", 2, 20, 0], ["makine", 3, 45, 4], ["kuyruk", 1, 30, 1],
  ["veri_deposu", 1, 180, 12], ["nesne_deposu", 1, 15, 1]];
const ADET = KAYNAK.reduce((s, [, n]) => s + n, 0);
const YARATMA = KAYNAK.reduce((s, [, n, y]) => s + n * y, 0);
const SAATLIK = KAYNAK.reduce((s, [, n, , u]) => s + n * u, 0);
const UCTAN_UCA_SURE = YARATMA + 60 + YARATMA / 2; // yaratma + akis dogrulamasi + silme

// AD17: sozlesme dogrulamasi yalniz arayuz alanlarina bakar
const SOZLESME_ALANI = ["bolge", "cikti", "disk_gb"];
const SEVIYE = [
  ["birim", (k) => k.katman === "tanim", 12, 0, 0],
  ["sozlesme", (k) => k.katman === "iliski" ||
    (k.katman === "tanim" && SOZLESME_ALANI.includes(k.alan)), 45, 0, 0],
  ["uctan uca", (k) => k.katman !== "degisim" && k.yol === "ana",
    UCTAN_UCA_SURE, ADET, (SAATLIK * UCTAN_UCA_SURE) / 3600],
];

const tuttugu = SEVIYE.map(([, f]) => KUSUR.filter(f).map((k) => k.kod));
console.log(`${"seviye".padEnd(11)}${"tuttugu".padStart(9)}${"yalniz kendisi".padStart(16)}` +
  `${"kacirdigi".padStart(11)}${"yaratilan kaynak".padStart(18)}${"sure".padStart(9)}` +
  `${"maliyet (kurgu birim)".padStart(23)}`);
SEVIYE.forEach(([ad, , sure, kaynak, ucret], j) => {
  const yalniz = tuttugu[j].filter((k) => tuttugu.every((t, o) => o === j || !t.includes(k)));
  console.log(`${ad.padEnd(11)}${`${tuttugu[j].length}/${KUSUR.length}`.padStart(9)}` +
    `${String(yalniz.length).padStart(16)}${String(KUSUR.length - tuttugu[j].length).padStart(11)}` +
    `${String(kaynak).padStart(18)}${`${sure} sn`.padStart(9)}${ucret.toFixed(2).padStart(23)}`);
});

const hepsi = new Set(tuttugu.flat());
const kacan = KUSUR.filter((k) => !hepsi.has(k.kod));
console.log(`\nuc seviye birlikte ${KUSUR.length} kusurun ${hepsi.size} tanesini tutar; ` +
  `toplam sure ${SEVIYE.reduce((s, [, , t]) => s + t, 0)} sn, ` +
  `maliyet ${SEVIYE.reduce((s, [, , , , u]) => s + u, 0).toFixed(2)} kurgu birim`);
console.log(`\nuc seviyenin de kacirdigi ${kacan.length} kusur (katman: ${kacan[0].katman}):`);
for (const k of kacan) console.log(`  ${k.kod}  ${k.ne}`);
console.log(`\nseviye basina kusur maliyeti: ` + SEVIYE.map(([ad, , sure, , ucret], j) =>
  `${ad} ${(sure / tuttugu[j].length).toFixed(1)} sn/kusur` +
  (ucret ? ` ve ${(ucret / tuttugu[j].length).toFixed(2)} birim/kusur` : "")).join("; "));
```

```
seviye       tuttugu  yalniz kendisi  kacirdigi  yaratilan kaynak     sure  maliyet (kurgu birim)
birim           5/15               3         10                 0    12 sn                   0.00
sozlesme        5/15               2         10                 0    45 sn                   0.00
uctan uca       7/15               3          8                 8   660 sn                   4.77

uc seviye birlikte 15 kusurun 12 tanesini tutar; toplam sure 717 sn, maliyet 4.77 kurgu birim

uc seviyenin de kacirdigi 3 kusur (katman: degisim):
  D13  alan degisikligi kaynagi yeniden olusturuyor, veri gidiyor
  D14  yerinde guncelleme sirasinda kesinti oluyor
  D15  kayit disi elle degisikligin uzerine yaziliyor

seviye basina kusur maliyeti: birim 2.4 sn/kusur; sozlesme 9.0 sn/kusur; uctan uca 94.3 sn/kusur ve 0.68 birim/kusur
```

## Kimin Neyi Tuttuğu

Üç seviye birlikte on beş kusurun on ikisini tutar. Tek başına bakıldığında hiçbiri yarıyı geçmez:
birim beş, sözleşme beş, uçtan uca yedi. Asıl bilgi "yalnız kendisi" sütunundadır, çünkü bir
seviyeyi hattan çıkarmanın bedeli orada yazar. Birim doğrulaması çıkarılırsa üç kusur kimsesiz
kalır — kuyruğun sıfır saklaması, arşivin yanlış sınıfı, yazılmamış sahip etiketi. Üçü de tek bir
kaynağın tanımında, göz önünde durur ve üçü de yan akıştadır; uçtan uca doğrulama gerçek kaynağı
yaratır ama o yollardan hiç geçmez.

Sözleşme doğrulamasının yalnız kendisine ait iki kusuru da aynı nedenle oradadır: kuyruk ile veri
deposunun ayrı bölgede olması ve yedek penceresinin bakım penceresiyle çakışması ancak iki kaynak
yan yana konunca görünür, ve ikisi de ana akışta değildir. Sözleşme doğrulamasının değeri
**karşılaştırmadadır**, koşumda değil; bu yüzden kaynak yaratmadan bir uçtan uca testin
göremeyeceğini görür.

Örtüşme de sayılabilir. Yakalanan on iki kusurdan biri — makinenin on gigabaytlık diski — üç
seviyenin üçüne birden takılır: tanımda yazılıdır, sözleşme alanlarından biridir ve ana akışta
koşarken de kendini gösterir. Üçü de aynı kusuru raporlar, ekip aynı şeyi üç kez okur. Üç kusur iki
seviyeye takılır, geri kalan sekizi tek bir seviyenin işidir. Bir hattın kapı sırasını belirleyen
şey tam da bu dağılımdır.

Uçtan uca doğrulamanın üç kusuru ise ancak koşum katmanında vardır: kesen bir güvenlik kuralı,
bağlanmayan bir disk, eksik bir yetki. Bunların hiçbiri kayıtta yanlış yazılmamıştır — kayıt
doğrudur, gerçek farklıdır. Bu, kursun ölçü ekseninin en açık hâlidir: metin ile gerçek arasındaki
fark ancak gerçek çalıştırılınca ölçülür.

## Süre ve Maliyet

Son üç sütun aynı kapsamın fiyatıdır. Birim doğrulaması on iki saniyede biter, hiç kaynak
yaratmaz, ücreti sıfırdır. Sözleşme doğrulaması kırk beş saniye sürer — plan üretimini bekler — ama
yine hiçbir şey yaratmaz. Uçtan uca doğrulama sekiz gerçek kaynak açar, altı yüz altmış saniye
sürer ve 4,77 kurgu birim tutar; süresinin dörtte üçü yaratma ve silmedir, doğrulamanın kendisi
altmış saniyedir.

Kusur başına bakıldığında fark daha keskindir: birim 2,4 saniye/kusur, sözleşme 9,0 saniye/kusur,
uçtan uca 94,3 saniye ve 0,68 birim/kusur. Uçtan uca doğrulama bir kusuru birim doğrulamasının
kırk katı sürede tutar. Bu, "uçtan uca kötüdür" demek değildir — tuttuğu üç kusuru başka hiçbir
seviye tutamaz. Söylediği şey, **her seviyenin kendi katmanında en ucuz olduğu**: aynı kusuru iki
seviyede sınamak, kusuru pahalı olanda ikinci kez ödemektir.

Sıra da bu tablodan okunur. Birim doğrulaması on iki saniyede beş kusuru eler; ondan sonra koşan
uçtan uca doğrulama o beşini artık aramaz. Ters sıranın bedeli de hesaplanabilir: uçtan uca önce
koşarsa, birim doğrulamasının on iki saniyede bulacağı bir kusur için sekiz gerçek kaynak
yaratılmış, altı yüz altmış saniye beklenmiş ve 4,77 birim ödenmiş olur. Aynı kusurun bedeli, hangi
kapıda yakalandığına göre kırk kata kadar değişir.

## Üç Seviyenin Ortak Boşluğu

Kaçan üç kusurun ortak adı çıktıda yazılıdır: **değişim katmanı**. Üç seviye de doğrulamayı
sıfırdan kurulan temiz bir ortamda yapar. Gerçek değişiklik ise sıfırdan kurulmuş bir ortama değil,
**var olan altyapının üzerine** uygulanır — ve kusurlar tam orada doğar: bir alanın değişmesi
kaynağı yeniden oluşturur ve içindeki veri gider; yerinde bir güncelleme kesinti üretir; kayıt dışı
yapılmış elle bir değişikliğin üzerine yazılır.

Üçünü de sınamak boş ortamda kurulan bir testle olanaksızdır, çünkü sınanacak şey **geçmişin
kendisidir**: kaynağın hâlihazırda taşıdığı veri, hâlihazırda aldığı trafik, hâlihazırda üzerinde
yapılmış kayıt dışı değişiklik. Bu boşluğu kapatan şey bir test seviyesi değil, uygulamadan önce
okunan plandır — hangi kalemin yeniden oluşturulacağını orada yazar. Kaydın kapsamadığı elle
değişiklik ise ne testte ne planda görünür; onun tek karşılığı sapmanın ayrıca ölçülmesidir.

## Temizlenmeyen Kaynak

Uçtan uca doğrulamanın tablodaki 4,77 birimlik maliyeti, temizleme adımının her koşumda başarılı
olduğunu varsayar. Silme de yaratma gibi bir uygulama adımıdır ve o da başarısız olabilir: hat
zaman aşımına uğrar, bir kaynak başka bir kaynağa bağlı olduğu için silinemez, koşum yarıda kesilir.

```js
// artik.mjs — uctan uca dogrulamanin biraktigi artik kaynak ve sizan maliyet (model)

// AD18: otuz gun boyunca gunde bir uctan uca kosum; temizleme adimi bes kosumdan birinde
// basarisiz olur ve basarisiz kosumda her kaynak yarim olasilikla ayakta kalir (kurgu)
const TOHUM = 20260215;
let durum = TOHUM;
const rast = () => (durum = (durum * 48271) % 2147483647) / 2147483647; // carpim 2^53 altinda kalir

const KAYNAK = [["ag", 2, 0], ["makine", 3, 4], ["kuyruk", 1, 1], ["veri_deposu", 1, 12],
  ["nesne_deposu", 1, 1]]; // tur, adet, saatlik kurgu birim
const ORNEK = KAYNAK.flatMap(([t, n, u]) => Array.from({ length: n }, (_, i) => [`${t}-${i + 1}`, u]));
const GUN = 30, HATA = 0.2, KOSUM_UCRETI = 4.77; // 4.77: onceki blokta hesaplanan kosum maliyeti

const kalan = [];
let hatali = 0, sizan = 0;
for (let g = 1; g <= GUN; g += 1) {
  if (rast() < HATA) {
    hatali += 1;
    for (const [ad, u] of ORNEK) if (rast() < 0.5) kalan.push({ ad: `${ad}#k${g}`, u, gun: g });
  }
  sizan += kalan.reduce((s, k) => s + k.u, 0) * 24; // birikmis artik gun boyu ucret isletir
}

const amaclanan = GUN * KOSUM_UCRETI;
console.log(`${GUN} gun, ${GUN} kosum, tohum ${TOHUM}: temizleme ${hatali} kosumda basarisiz, ` +
  `${kalan.length} artik kaynak birikti`);
console.log(`\n${"artik kaynak".padEnd(20)}${"birakildigi gun".padStart(16)}` +
  `${"saatlik ucret".padStart(14)}${"ay sonuna dek ucret".padStart(21)}`);
for (const k of kalan) {
  console.log(`${k.ad.padEnd(20)}${String(k.gun).padStart(16)}${String(k.u).padStart(14)}` +
    `${String(k.u * 24 * (GUN - k.gun + 1)).padStart(21)}`);
}
console.log(`\namaclanan maliyet (${GUN} kosum x ${KOSUM_UCRETI}) ${amaclanan.toFixed(2)} birim; ` +
  `sizan maliyet ${sizan.toFixed(2)} birim; oran ${(sizan / amaclanan).toFixed(1)}x`);
const pahali = [...kalan].sort((a, b) => b.u - a.u)[0];
console.log(`ay sonundaki artik saatlik ucret ${kalan.reduce((s, k) => s + k.u, 0)} birim; ` +
  `en pahali artik ${pahali.ad} (${pahali.u} birim/saat); ` +
  `kayitta gorunen artik kaynak sayisi 0`);
```

```
30 gun, 30 kosum, tohum 20260215: temizleme 4 kosumda basarisiz, 11 artik kaynak birikti

artik kaynak         birakildigi gun saatlik ucret  ay sonuna dek ucret
ag-1#k3                            3             0                    0
kuyruk-1#k3                        3             1                  672
veri_deposu-1#k3                   3            12                 8064
nesne_deposu-1#k3                  3             1                  672
ag-2#k12                          12             0                    0
makine-3#k12                      12             4                 1824
veri_deposu-1#k12                 12            12                 5472
makine-1#k24                      24             4                  672
ag-1#k29                          29             0                    0
kuyruk-1#k29                      29             1                   48
veri_deposu-1#k29                 29            12                  576

amaclanan maliyet (30 kosum x 4.77) 143.10 birim; sizan maliyet 18000.00 birim; oran 125.8x
ay sonundaki artik saatlik ucret 47 birim; en pahali artik veri_deposu-1#k3 (12 birim/saat); kayitta gorunen artik kaynak sayisi 0
```

Otuz koşumun dördünde temizleme başarısız oldu ve on bir kaynak ayakta kaldı. Otuz koşumun
amaçlanan maliyeti 143 kurgu birimdi; sızan maliyet 18.000 birim, yani **yüz yirmi altı katı**.
Oranı bu kadar büyüten şey başarısızlık sayısı değil süredir: koşum on bir dakika sürer, artık
kaynak ise fark edilene kadar günlerce durur. Üçüncü günün veri deposu tek başına 8.064 birim
işletmiştir.

Tabloda okunacak ikinci bir şey daha var. On bir artığın yedisi üçüncü ve on ikinci günde
bırakılmıştır ve sızan maliyetin neredeyse tamamını onlar üretir: üçüncü günün dört artığı 9.408
birim, on ikinci günün üç artığı 7.296 birim işletirken yirmi dokuzuncu günün üç artığı yalnız 624
birim işletir. Temizlik başarısızlığının bedeli sabit değildir, **fark edilme süresiyle** çarpılır;
bu yüzden artık kaynağı azaltmanın yolu temizliği yüzde yüz başarılı kılmak değil, artığı erken
bulmaktır.

Son satır bu kursun ölçü ekseniyle doğrudan bağlıdır: **kayıtta görünen artık kaynak sayısı
sıfırdır.** Bu kaynakları kayıt yaratmadı, test yarattı; kaydın durumu onları içermez, kayda bakan
hiç kimse onları göremez. Testin bıraktığı artık, kaydın kapsamadığı altyapının en sessiz
biçimidir — ve onu bulmanın tek yolu sağlayıcıyı kayıtla karşılaştırmaktır.

## Özet

- On beş kusurluk küme üç doğrulama seviyesinde koşturuldu: birim 5, sözleşme 5, uçtan uca 7 kusur
  tuttu; üçü birlikte 12'sini tuttu, hiçbiri tek başına yarıyı geçmedi.
- Yalnız kendisinin tuttuğu kusur sayısı 3, 2 ve 3'tür; sözleşme doğrulaması kaynak yaratmadan iki
  ilişki kusurunu tutar, uçtan uca doğrulama ise üç koşum kusurunu başka hiçbir seviyenin
  göremeyeceği biçimde tutar.
- Maliyet katmanla birlikte büyür: birim 12 sn ve 0 kaynak, sözleşme 45 sn ve 0 kaynak, uçtan uca
  660 sn, 8 gerçek kaynak ve 4,77 kurgu birim; kusur başına 2,4 / 9,0 / 94,3 saniye.
- Üç seviyenin ortak boşluğu **değişim katmanıdır**: üçü de sıfırdan kurulan temiz ortamda koşar,
  oysa gerçek değişiklik var olan altyapının üzerine uygulanır (yeniden oluşturma ve veri kaybı,
  yerinde güncelleme kesintisi, kayıt dışı elle değişikliğin üzerine yazılması).
- Otuz koşumda temizleme 4 kez başarısız oldu, 11 artık kaynak kaldı; amaçlanan 143 birime karşı
  18.000 birim sızdı (126 kat) ve bu kaynakların kayıtta görünen sayısı sıfırdır.

## Sonraki Adım

Bu dersin son iki sayısı aynı yere bakıyor: uçtan uca doğrulamanın koşum maliyeti ve artık
kaynağın sızan maliyeti. İkisi de değişikliğin **parasal** yüzüdür ve ikisi de ancak olan bitince
sayıldı. Oysa aynı soru uygulamadan önce sorulabilir: bu değişiklik uygulanırsa aylık gider ne
kadar artar? Sonraki ders plan üzerinden değişiklik başına tahmin üretir ve gerçekleşenle
karşılaştırır — hangi kalem sabit birim fiyatlı olduğu için tahmin edilebiliyor, hangi kalem
kullanıma bağlı olduğu için edilemiyor, tahmin hatası nasıl dağılıyor ve "tahmin şu kadarı aşarsa
dur" biçiminde bir eşik kuralı bilinen değişiklik kümesinde kaç değişikliği gereksiz yere
durduruyor.
