Ders 02 / 11
Risk Temelli Önceliklendirme
Aynı bütçenin beş ayrı sırayla dağıtılması: olasılık ile etkinin çarpımından türeyen sınıf riski, risk sırasının dakikaya bölünmesiyle ortaya çıkan yoğunluk sırası, rastgele ve en ucuz ile en çok bileşene dokunan sıralarla karşılaştırma, tahmin hatasının duyarlılığı ve sıranın yirmi sürümlük geri dönüşü.
İçindekiler
Önceki ders bütçeye sığan planı en ucuz testleri sırayla alarak kurdu; o sıralamanın tek gerekçesi yüz yirmi dakikaya çok kalem sığdırmaktı. Oysa her kusurun bir olasılığı ve bir etkisi var, ve bir testin ucuzluğu bunların ikisiyle de ilgili değil. Aynı bütçe başka bir sırayla dağıtılsaydı ne değişirdi.
Bu ders sıralamayı bir karara dönüştürür. Risk temelli önceliklendirme (risk-based prioritization) sınırlı bütçeyi kusur sınıflarının riskine göre dağıtır; risk burada iki niceliğin çarpımıdır — bir kusurun ortaya çıkma olasılığı (likelihood) ve ortaya çıktığında verdiği etki (impact). Dağıtılan kaynak yine sürüm başına 120 dakikadır (TS3); ölçülen şey yine kaçan hata ile geri bildirim süresidir.
Risk Puanı ve Onun Tahmini
Bir kusurun risk puanı olasılık ile etkinin çarpımıdır; bir sınıf riski o sınıftaki kusurların risk puanları toplamıdır. Kusur kümesindeki olasılık ve etki değerleri birinci dersin tohumundan gelir, uydurulmaz.
TS8 (varsayım) — risk puanı olasılık × etkidir, iki nicelik eşit ağırlıklıdır. TS9 (varsayım) — plan gerçek sınıf riskini bilmez, tahmin eder; tahmin gerçeğin katıdır ve taban durumda ’dir. Gerçek sınıf riski ancak kusurlar ortaya çıktıktan sonra bilinir; sıralama öncesinde yapılır. TS10 (varsayım) — bir testin ayağa kaldırdığı süreç sayısı, dokunduğu bileşen sayısının gözlenebilir vekilidir. “En çok kod dokunan önce” sırası bu vekille kurulur; süreç sayıları kapanış tablolarından okunmuştur.
// kutuphane/envanter.mjs — birinci dersin envanteri ve kusur kumesi, kisa yazimla. // Bedel nicelikleri M21/K03 ve M21/K04 kapanis tablolarindan; dakikaya cevrim TS1-TS2. const HAM = [ ["T01", "birim testi kumesi", "birim", 0, 266, 0, "kural-siniri"], ["T02", "tumlesim testi", "tumlesim", 1, 772, 0, "sema-uyusmazligi"], ["T03", "veritabani goc testi", "tumlesim", 1, 21, 0, "goc-veri-kaybi"], ["T04", "sozlesme testi", "sozlesme", 2, 100, 0, "sozlesme-alani"], ["T05", "uctan uca tarayici testi", "uctan-uca", 2, 16477, 0, "arayuz-durumu"], ["T06", "gorsel dogrulama", "uctan-uca", 1, 784, 1, "gorsel-sapma"], ["T07", "yuk testi", "basarim", 9, 55000, 0, "veri-buyumesi"], ["T08", "statik guvenlik taramasi", "guvenlik", 0, 75, 7, "sql-birlestirme"], ["T09", "bagimlilik taramasi", "guvenlik", 0, 10, 5, "bilinen-acik"], ["T10", "erisilebilirlik denetimi", "guvenlik", 0, 14, 6, "erisilebilirlik"], ["T11", "hata enjeksiyonu", "dayaniklilik", 1, 13, 5, "bozulmus-yanit"], ["T12", "kurtarma dogrulamasi", "dayaniklilik", 2, 7, 10, "kurtarma-eksigi"], ]; export const TESTLER = HAM.map(([kod, ad, seviye, surec, cagri, elle, sinif]) => ({ kod, ad, seviye, surec, cagri, elle, sinif, dk: 0.5 * surec + 0.0002 * cagri + 6 * elle, })); export const ORTUSMEYEN = ["senaryo-disi", "anlam-sapmasi"]; const AGIRLIK = [["kural-siniri", 9], ["sema-uyusmazligi", 6], ["goc-veri-kaybi", 4], ["sozlesme-alani", 5], ["arayuz-durumu", 8], ["gorsel-sapma", 3], ["veri-buyumesi", 4], ["sql-birlestirme", 3], ["bilinen-acik", 3], ["erisilebilirlik", 4], ["bozulmus-yanit", 3], ["kurtarma-eksigi", 2], ["senaryo-disi", 5], ["anlam-sapmasi", 4]]; export function kusurlar(tohum, n) { let x = tohum; const rast = () => { x = (1103515245 * x + 12345) % 2147483648; return x / 2147483648; }; const toplam = AGIRLIK.reduce((a, [, w]) => a + w, 0); const liste = []; for (let i = 1; i <= n; i += 1) { let p = rast() * toplam, sinif = AGIRLIK[AGIRLIK.length - 1][0]; for (const [s, w] of AGIRLIK) { p -= w; if (p < 0) { sinif = s; break; } } liste.push({ no: i, sinif, olasilik: 1 + Math.floor(rast() * 5), etki: 1 + Math.floor(rast() * 5), duzeltme: 15 + 15 * Math.floor(rast() * 8) }); } return liste; }
Aynı Bütçe, Beş Sıra
Sıra bir test listesidir; bütçe dolana kadar sırayla alınır, sığmayan atlanır. Beş sıra karşılaştırılır: tahmini riske göre azalan (S1), tahmini riskin dakikaya bölümüne göre azalan (S2), en ucuz önce (S3, birinci dersin sırası), rastgele (S4), en çok bileşene dokunan önce (S5).
// kutuphane/risk.mjs — ayni butce, bes sira, ayni kusur kumesi. Girdi: kutuphane/envanter.mjs import { TESTLER, ORTUSMEYEN, kusurlar } from "./envanter.mjs"; const BUTCE = 120, TOHUM = 20260731, N = 60, KAT = 6, ADAY = 20; // TS3, TS5, TS6 const KUSUR = kusurlar(TOHUM, N); const SINIF = [...new Set([...TESTLER.map((t) => t.sinif), ...ORTUSMEYEN])]; const v = (x, n = 1) => x.toFixed(n).replace(".", ","); const g = (x, n) => String(x).padStart(n); const uret = (tohum) => { let x = tohum; return () => { x = (1103515245 * x + 12345) % 2147483648; return x / 2147483648; }; }; // TS8: risk puani = olasilik x etki; sinif riski o siniftaki kusurlarin risk toplamidir. const GERCEK = new Map(SINIF.map((s) => [s, KUSUR.filter((k) => k.sinif === s) .reduce((a, k) => a + k.olasilik * k.etki, 0)])); // TS9: plan gercek riski bilmez, tahmin eder; tahmin [1-e, 1+e] carpaniyla sapar. const tahmin = (e, r) => new Map(SINIF.map((s) => [s, GERCEK.get(s) * (1 - e + 2 * e * r())])); // Sirali listeden butceye sigani al; sigmayan atlanir, sira bozulmaz. const sec = (sira) => { const c = []; let t = 0; for (const x of sira) if (t + x.dk <= BUTCE) { c.push(x); t += x.dk; } return c; }; function olc(c) { const an = new Map(); let t = 0; for (const x of c) { t += x.dk; an.set(x.sinif, t); } const yak = KUSUR.filter((k) => an.has(k.sinif)), kac = KUSUR.filter((k) => an.has(k.sinif) === false); return { n: c.length, kod: c.map((x) => x.kod).join(" "), sure: t, yak: yak.length, kac: kac.length, oran: (100 * kac.length) / KUSUR.length, risk: kac.reduce((a, k) => a + k.olasilik * k.etki, 0), geri: yak.reduce((a, k) => a + an.get(k.sinif), 0) / (yak.length || 1), duz: kac.reduce((a, k) => a + k.duzeltme, 0) }; } const risksira = (T) => [...TESTLER].sort((a, b) => T.get(b.sinif) - T.get(a.sinif)); const yogunsira = (T) => [...TESTLER].sort((a, b) => T.get(b.sinif) / b.dk - T.get(a.sinif) / a.dk); const TOP = [...GERCEK.values()].reduce((a, x) => a + x, 0); const TABAN = ORTUSMEYEN.reduce((a, s) => a + GERCEK.get(s), 0); console.log(`sinif riski (TS8) ve tahmin (TS9, e = %50) — tohum ${TOHUM}, ${N} kusur, ${SINIF.length} sinif`); console.log("sinif kusur gercek tahmin test dk tahmin/dk"); const T50 = tahmin(0.5, uret(8125)); for (const s of SINIF) { const t = TESTLER.find((x) => x.sinif === s); console.log(s.padEnd(18) + g(KUSUR.filter((k) => k.sinif === s).length, 5) + g(GERCEK.get(s), 8) + g(v(T50.get(s)), 8) + " " + (t ? t.kod : "yok ") + g(t ? v(t.dk, 2) : "-", 7) + g(t ? v(T50.get(s) / t.dk, 2) : "-", 11)); } console.log(`toplam risk ${TOP}; hicbir testin gormedigi iki sinif ${TABAN} puan -> erisilebilir risk ${TOP - TABAN}`); const S = { S1: risksira(T50), S2: yogunsira(T50), S3: [...TESTLER].sort((a, b) => a.dk - b.dk), S5: [...TESTLER].sort((a, b) => b.surec - a.surec || b.cagri - a.cagri) }; const AD = { S1: "S1 risk azalan (tahmin)", S2: "S2 tahmin/dk azalan", S3: "S3 en ucuz once", S5: "S5 en cok bilesen once" }; const r4 = uret(4242), rast = []; for (let i = 0; i < 200; i += 1) { const p = [...TESTLER]; for (let j = p.length - 1; j > 0; j -= 1) { const q = Math.floor(r4() * (j + 1)); [p[j], p[q]] = [p[q], p[j]]; } rast.push(olc(sec(p))); } const ort = (f) => rast.reduce((a, o) => a + f(o), 0) / rast.length; // Son sutun kararin geri donusudur: ADAY surumluk kosum + kacan hatanin KAT'li duzeltmesi. console.log(`\nayni butce TS3 = ${BUTCE} dk, ayni kusur kumesi; son sutun TS5-TS6 ile ${ADAY} surumluk`); console.log("sira test sure kacan kacak% kacan risk geri bd toplam dk"); const w = (x) => (Number.isInteger(x) ? String(x) : v(x, 2)); const yaz = (ad, o) => console.log(ad.padEnd(30) + g(w(o.n), 5) + g(v(o.sure), 7) + g(w(o.kac), 7) + g(v(o.oran), 8) + g(v(o.risk), 12) + g(v(o.geri), 9) + g(v(ADAY * o.sure + KAT * o.duz, 0), 11)); for (const k of ["S1", "S2", "S3", "S5"]) yaz(AD[k], olc(sec(S[k]))); yaz("S4 rastgele (200 permutasyon)", { n: ort((o) => o.n), sure: ort((o) => o.sure), kac: ort((o) => o.kac), oran: ort((o) => o.oran), risk: ort((o) => o.risk), geri: ort((o) => o.geri), duz: ort((o) => o.duz) }); console.log(`S4 yayilimi: kacan risk en iyi ${Math.min(...rast.map((o) => o.risk))}, ` + `en kotu ${Math.max(...rast.map((o) => o.risk))}; 200 permutasyonun ` + `${rast.filter((o) => o.risk <= olc(sec(S.S2)).risk).length} tanesi S2 kadar iyi`); for (const k of ["S1", "S5"]) console.log(k + " secilen: " + olc(sec(S[k])).kod); console.log("\ntahmin hatasi TS9'un duyarliligi — e basina 200 cizim, ortalama kacan risk"); console.log("e S1 ortalama S2 ortalama S2 > S3 olan cizim en kotu S2"); const S3R = olc(sec(S.S3)).risk; for (const e of [0, 0.25, 0.5, 1]) { const r = uret(9001); let a = 0, b = 0, yenik = 0, kotu = 0; for (let i = 0; i < 200; i += 1) { const T = tahmin(e, r); const o1 = olc(sec(risksira(T))), o2 = olc(sec(yogunsira(T))); a += o1.risk; b += o2.risk; kotu = Math.max(kotu, o2.risk); if (o2.risk > S3R) yenik += 1; } console.log(g("%" + Math.round(100 * e), 4) + g(v(a / 200), 12) + g(v(b / 200), 13) + g(yenik, 21) + g(kotu, 12)); } console.log(`karsilastirma tabani: S3 en ucuz once, kacan risk ${S3R}`);
sinif riski (TS8) ve tahmin (TS9, e = %50) — tohum 20260731, 60 kusur, 14 sinif sinif kusur gercek tahmin test dk tahmin/dk kural-siniri 7 63 40,8 T01 0,05 766,99 sema-uyusmazligi 7 65 60,2 T02 0,65 92,04 goc-veri-kaybi 3 15 21,6 T03 0,50 42,85 sozlesme-alani 7 75 101,7 T04 1,02 99,68 arayuz-durumu 4 39 24,0 T05 4,30 5,58 gorsel-sapma 2 23 33,2 T06 6,66 4,99 veri-buyumesi 6 51 64,5 T07 15,50 4,16 sql-birlestirme 3 51 57,3 T08 42,02 1,36 bilinen-acik 3 33 28,4 T09 30,00 0,95 erisilebilirlik 4 32 32,5 T10 36,00 0,90 bozulmus-yanit 3 21 12,9 T11 30,50 0,42 kurtarma-eksigi 1 9 5,3 T12 61,00 0,09 senaryo-disi 4 33 49,1 yok - - anlam-sapmasi 6 60 78,7 yok - - toplam risk 570; hicbir testin gormedigi iki sinif 93 puan -> erisilebilir risk 477 ayni butce TS3 = 120 dk, ayni kusur kumesi; son sutun TS5-TS6 ile 20 surumluk sira test sure kacan kacak% kacan risk geri bd toplam dk S1 risk azalan (tahmin) 9 106,7 17 28,3 156,0 48,9 8434 S2 tahmin/dk azalan 9 100,7 18 30,0 155,0 18,2 9574 S3 en ucuz once 9 89,2 18 30,0 185,0 16,5 9704 S5 en cok bilesen once 9 119,7 20 33,3 197,0 61,4 11484 S4 rastgele (200 permutasyon) 8,48 111,7 21,36 35,6 207,1 75,8 11220 S4 yayilimi: kacan risk en iyi 155, en kotu 377; 200 permutasyonun 17 tanesi S2 kadar iyi S1 secilen: T04 T07 T02 T08 T01 T06 T10 T05 T03 S5 secilen: T07 T05 T04 T12 T06 T02 T03 T01 T09 tahmin hatasi TS9'un duyarliligi — e basina 200 cizim, ortalama kacan risk e S1 ortalama S2 ortalama S2 > S3 olan cizim en kotu S2 %0 155,0 155,0 0 155 %25 155,7 156,4 0 174 %50 161,8 161,6 4 186 %100 175,5 167,3 20 204 karsilastirma tabani: S3 en ucuz once, kacan risk 185
Sayı Saymak ile Risk Saymak
Altmış kusurdan yakalananlar 43, 42, 42, 40 ve ortalama 38,64’tür; kaçan hata sayısı beş sırayı zor ayırır: 17, 18, 18, 20 ve ortalama 21,36. Kaçan hatanın risk toplamı ise ayırır: 156, 155, 185, 197 ve ortalama 207,1. Farkı yaratan, birinin her kusuru bir sayması, ötekinin ağırlığıyla saymasıdır. S2 ile S3 aynı sayıda kusuru kaçırır, ama S3’ün kaçırdıkları 30 risk puanı daha ağırdır.
Karşılaştırmanın tabanı da tabloda: toplam 570 riskin 93 puanı hiçbir testin görmediği iki sınıfa aittir, yani sıranın oynayabileceği aralık 477 puandır. S2 bu aralığın 62 puanını kaçırır, S3 ise 92 puanını — yalnız sıra değiştirerek 1,48 kat fark. Tabana bakmadan yazılan bir “kaçan risk 155” cümlesi bu oranı gizler.
Risk Sırası ile Yoğunluk Sırası
S1 ile S2 aynı tahmini kullanır ve neredeyse aynı kaçan riske varır (156’ya karşı 155). Ayrım başka yerdedir: S1’in geri bildirim süresi 48,9 dakika, S2’ninki 18,2 — 2,7 kat. Nedeni seçilen sıralarda görünür. S1 dördüncü sıraya 42,02 dakikalık statik güvenlik taramasını koyar, çünkü o sınıfın tahmini riski yüksektir; S2 aynı testi sona atar, çünkü dakikaya bölündüğünde tahmin/dk değeri 1,36’dır. Yüksek riskli ama pahalı bir kalem sıranın başına konduğunda kendinden sonraki her testin haber verme anını geciktirir.
Risk sırası tek başına yanlış sıradır; bölen dakikadır. T01’in tahmin/dk değeri 766,99, T12’ninki 0,09 — hiçbir risk sıralamasının tek başına göremeyeceği bir fark.
S5 bu noktayı tersinden gösterir: en çok bileşene dokunan sıra ilk iki kalemine yük testi ile kurtarma doğrulamasını alır, 120 dakikanın 76,5’ini iki testle harcar ve 20 kusur kaçırır. Çok koda dokunmak, çok risk görmek değildir. S4 ise sıranın kendisinin bir kazanç olduğunu gösterir: iki yüz permütasyonun ortalaması 207,1, en kötüsü 377, yalnız 17’si S2 kadar iyi. Sırası yazılmamış plan, ortalamada rastgele plandır.
Tahminin Yanılma Payı
Sıralama gerçek riske değil tahmine dayanır ve tahmin yanılır. Duyarlılık taraması her hata düzeyi için iki yüz çizim yapar. Hata sıfırken iki sıra da 155’te buluşur — üst sınır budur. Hata ±%50’ye çıktığında S2’nin ortalaması 161,6 olur ve iki yüz çizimin yalnız dördü en ucuz önce sırasının 185’inden kötüdür. Hata ±%100 iken ortalama 167,3’te kalır, yenilen çizim sayısı 20’ye çıkar, en kötü çizim 204 olur.
Kazanç yavaş erir, çünkü sıra tahminin değerini değil düzenini kullanır: bir sınıfın riski iki katı yanlış tahmin edilse bile listedeki yeri çoğu zaman aynı kalır. Buradan çıkan kural, tahminin kaynağının yazılmasıdır — kusur geçmişindeki sınıf dağılımı, değişiklik yoğunluğu, etkilenen kullanıcı sayısı. Kaynağı yazılmamış bir risk sırası bir tercih listesidir; ±%100 satırı o tercihin bedelini verir.
Kararın Geri Dönüşü
Tablonun son sütunu — yirmi sürümlük koşum artı kaçan hatanın altı katlı düzeltmesi — sıralamayı üçüncü bir nicelikle sınar: S1 8.434 dakikayla en ucuzdur, S2 9.574, S3 9.704, rastgele 11.220, en çok bileşen 11.484. S1’in kaçan riski S2’den yüksek olmasına karşın toplam bedeli düşüktür, çünkü risk puanı düzeltme maliyetini ölçmez: kusur kümesinde düzeltme dakikası olasılıktan ve etkiden bağımsız çekilir. Bir sıra üç niceliği birden eniyileyemez; hangisinin eniyileneceği plana yazılır.
Kırmızı sonucun anlamı da sıradan gelir. Tahmini riski en yüksek sınıfların testleri — sözleşme testi ve tümleşim testi — kırmızıya döndüğünde sürüm adayı ilerlemez; kuyruktaki kalemler bir kayıt açar. Sıranın kendisi de bir bakım kalemidir: kusur geçmişi değiştikçe sınıf riski değişir, yeniden türetilmeyen bir risk sırası birkaç sürüm sonra bir alışkanlığa dönüşür ve kazancı ±%100 satırındaki değerlere iner.
Özet
- Risk puanı olasılık ile etkinin çarpımıdır (TS8); sınıf riskini plan bilmez, tahmin eder (TS9).
- Kaçan hata sayısı beş sırayı 17 ile 21,36 arasında ayırır, kaçan risk 155 ile 207,1 arasında; ağırlıksız sayma sıralamanın kazancını gizler.
- Toplam 570 riskin 93 puanı hiçbir testin görmediği iki sınıfa aittir; sıranın oynadığı aralık 477’dir ve bu aralıkta S2 ile S3 arasındaki fark 1,48 kattır.
- Risk sırası pahalı bir kalemi öne alarak geri bildirimi 48,9 dakikaya çıkarır; aynı tahmin dakikaya bölündüğünde kaçan risk 155’te kalır, geri bildirim 18,2 dakikaya iner.
- Tahmin hatası ±%100’e çıktığında yoğunluk sırasının ortalaması 167,3 olur ve iki yüz çizimin 20’si en ucuz önce sırasına yenilir; kazanç yavaş erir.
- Risk puanı düzeltme maliyetini ölçmez: en düşük kaçan riske sahip sıra en ucuz sıra olmayabilir.
Sonraki Adım
Beş sıra da aynı on iki testin içinden seçim yaptı ve hiçbiri 93 puanlık tabana dokunamadı.
O tabanın 33 puanı senaryo-disi sınıfına ait: yazılmış hiçbir senaryonun geçmediği yollarda
ortaya çıkan dört kusur. Bu sınıfı görmenin yolu sırayı değiştirmek değil, sınama biçimini
değiştirmektir — betiği önceden yazılmamış, yönü sınama sırasında belirlenen bir oturum.
Sonraki ders o oturumu bir bütçe kalemi hâline getirir: kapsamın darlığı oturumun bulduğunu
nasıl değiştiriyor ve bulunan kusurun ne kadarı betikli kümeye dönüşüyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.