İçeriğe geç
academia.sh

Ders 01 / 11

Test Planı

Sınırlı bir sürüm bütçesinin dört kursta yazılmış test kümesi arasında paylaştırılması: envanterin bedel nicelikleriyle birlikte listelenmesi, giriş ile çıkış ölçütlerinin sayıya bağlanması, sorumluluğun koşan test sayısını belirlemesi ve dört planın aynı kusur kümesi üzerinde kaçan hata ile geri bildirim süresi bakımından karşılaştırılması.

İçindekiler

İşlevsel Olmayan Test kursunun kapanışı dört kursluk birikimi tek bir soruyla kapattı: hangi test ne zaman koşacak. Bu testlerin bazısı her değişiklikte koşacak kadar ucuz, bazısı sürüm başına bir kez koşacak kadar pahalı; sınırlı zamanın aralarında nasıl paylaştırılacağı hiçbir derste ele alınmadı.

Bu kursun her dersi aynı biçimi izler: sınırlı bir kaynak dağıtılır, dağıtımın ürettiği kaçan hata (escaped defect) ile geri bildirim süresi ölçülür ve kırmızı bir sonucun hangi karara dönüştüğü yazılır. Kaçan hata, Tümleşim, Sözleşme ve Uçtan Uca Test kursundaki kaçan gerçek hata ile aynı kavramdır; bu kursta kısa biçim kullanılır.

Planın Üç Sütunu

Bir test planı (test plan) üç şeyi yazar: kapsam hangi kusur sınıflarının sınanacağını, ölçüt planın ne zaman başlayıp ne zaman kapanacağını, sorumluluk her kalemin sahibini söyler. Üçü de birer sayıya bağlanmadıkça plan bir niyet metnidir.

Ölçütün iki yüzü vardır. Giriş ölçütü (entry criteria) bir aşamanın koşmaya başlayabilmesi için gereken koşuldur; sağlanmadan koşan test bilgi üretmez, zaman harcar. Çıkış ölçütü (exit criteria) planın kapandığını söyler ve bu derste kapsanan kusur sınıfı payına bağlanır.

Envanter: Dört Kursun Testleri Bir Liste

Kütüphane ödünç sisteminde dört kurs boyunca on iki test biçimi yazıldı. Her birinin bedeli kaynak dersin kapanış tablosunda koşumdan bağımsız bir nicelikle kayıtlı: kaç süreç, kaç istek ya da sorgu, kaç elle inceleme adımı. Bunlar iki varsayımla dakikaya çevrilir.

TS1 (varsayım) — koşum dakikası: süreç başına 0,5 dk, çağrı başına 0,0002 dk. Süreç payı, Tümleşim, Sözleşme ve Uçtan Uca Test kursundaki hazır olma yoklamasının altı adımından gelir; çağrı payı istek başına 12 milisaniyedir. TS2 (varsayım) — elle inceleme adımı başına 6 dk insan zamanı.

// kutuphane/envanter.mjs — dort kursta yazilmis test kumesi ve kursun ortak kusur kumesi.
// Bedel nicelikleri M21/K03 ile M21/K04 kapanis tablolarindan alinmistir; dakikaya cevrim
// TS1 (kosum) ve TS2 (insan) varsayimlariyla yapilir.
const HAM = [
  // kod, ad, seviye, surec, cagri, elle adim, yakaladigi kusur sinifi
  ["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,
  kosum: 0.5 * surec + 0.0002 * cagri,            // TS1
  insan: 6 * elle,                                // TS2
  dk: 0.5 * surec + 0.0002 * cagri + 6 * elle,
}));

// Otomatik kumenin hicbir uyesinin yakalamadigi iki sinif.
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;
}

İkinci yapı kusur kümesidir ve bu kursun bütün derslerinin ortak girdisidir: on dört sınıf, tohumdan türeyen olasılık, etki ve düzeltme dakikası. Sınıf adları kaynak derslerin yakaladığı kusurlardan alınmıştır. İkisini — senaryo-disi ve anlam-sapmasi — envanterdeki hiçbir test görmez; ikincisi Tümleşim, Sözleşme ve Uçtan Uca Test kursunun API testi dersinde “yakalamadığı” sütununa yazılan anlamsal uyuşmazlıktır.

Dört Plan, Aynı Kusur Kümesi

Plan bir sıralı test listesidir. Bir kusur, sınıfını gören ilk testin bittiği dakikada yakalanır; hiçbir test görmüyorsa kaçar. Kaçak oranı (defect leakage rate) kaçan kusurun küme içindeki payıdır.

TS3 (varsayım) — sürüm başına test bütçesi 120 dk. TS4 (varsayım) — çıkış ölçütü: kapsanan kusur sınıfı payı en az %70. TS5 (varsayım) — kaçan hatanın düzeltme maliyeti, yakalanmışın 6 katı. TS6 (varsayım) — ufuk 20 sürüm adayı; kusur kümesi bu ufuk boyunca ortaya çıkar. TS7 (varsayım) — adayların dörtte biri duman testinde kırmızıdır.

// kutuphane/plan.mjs — test planini bir veri yapisi olarak kurar ve ayni kusur kumesi
// uzerinde dort plani karsilastirir. Girdi: kutuphane/envanter.mjs
import { TESTLER, ORTUSMEYEN, kusurlar } from "./envanter.mjs";

const BUTCE = 120, ADAY = 20, KAT = 6, TOHUM = 20260731, N = 60;   // TS3, TS6, TS5
const SAHIP = { T01: "gelistirme", T02: "gelistirme", T03: "gelistirme", T04: "gelistirme",
  T05: "test", T06: "test", T07: "test", T08: "guvenlik", T09: "guvenlik",
  T10: "urun", T11: "isletme", T12: "isletme" };
const KUSUR = kusurlar(TOHUM, N);
const SINIF = [...new Set([...TESTLER.map((t) => t.sinif), ...ORTUSMEYEN])];
const v = (x, n = 2) => x.toFixed(n).replace(".", ",");
const g = (x, n) => String(x).padStart(n);

// Bir plan sirali bir test listesidir. Kacan hata = plandaki hicbir testin gormedigi kusur.
// Geri bildirim suresi = yakalanan kusurun yakalandigi birikimli dakikanin ortalamasi.
function olc(sira) {
  const an = new Map();
  let t = 0;
  for (const test of sira) { t += test.dk; an.set(test.sinif, t); }
  const yakalanan = KUSUR.filter((k) => an.has(k.sinif));
  const kacan = KUSUR.filter((k) => an.has(k.sinif) === false);
  return { test: sira.length, sinif: an.size, sure: t, kacan: kacan.length,
    oran: (100 * kacan.length) / KUSUR.length,
    geri: yakalanan.reduce((a, k) => a + an.get(k.sinif), 0) / (yakalanan.length || 1),
    duzeltme: kacan.reduce((a, k) => a + k.duzeltme, 0) };
}

const ucuz = [...TESTLER].sort((a, b) => a.dk - b.dk);
const sigan = [];
for (const t of ucuz) if (sigan.reduce((a, x) => a + x.dk, 0) + t.dk <= BUTCE) sigan.push(t);
const olcutlu = ucuz.slice(0, Math.ceil(0.7 * SINIF.length));       // cikis olcutu: %70 sinif
const sahipli = TESTLER.filter((t) => SAHIP[t.kod] !== "urun" && SAHIP[t.kod] !== "guvenlik");
const PLAN = [["P1 tam kapsam", TESTLER], ["P2 butceye sigan (olcutsuz)", sigan],
  ["P3 cikis olcutu >= %70", olcutlu], ["P4 tam kapsam, 3 kalem sahipsiz", sahipli]];

console.log("test envanteri — bedel nicelikleri M21/K03 ve M21/K04 kapanis tablolarindan");
console.log("kod  test                      seviye        kosum  insan  toplam  sinif            sahip");
for (const t of TESTLER) console.log(t.kod + "  " + t.ad.padEnd(26) + t.seviye.padEnd(12) +
  g(v(t.kosum), 6) + g(v(t.insan, 1), 7) + g(v(t.dk), 8) + "  " + t.sinif.padEnd(17) + SAHIP[t.kod]);
console.log("toplam".padEnd(44) + g(v(TESTLER.reduce((a, t) => a + t.kosum, 0)), 6) +
  g(v(TESTLER.reduce((a, t) => a + t.insan, 0), 1), 7) +
  g(v(TESTLER.reduce((a, t) => a + t.dk, 0)), 8) + "  " + TESTLER.length + "/" + SINIF.length + " sinif");

console.log(`\nkusur kumesi: tohum ${TOHUM}, ${N} kusur, ${SINIF.length} sinif`);
console.log("hicbir testin gormedigi sinif: " +
  ORTUSMEYEN.map((s) => `${s} (${KUSUR.filter((k) => k.sinif === s).length})`).join(", "));

console.log(`\nplan karsilastirmasi — butce TS3 = ${BUTCE} dk/surum, ufuk TS6 = ${ADAY} surum`);
console.log("plan                          test  sinif   sure   butce  kacan  kacak%  geri bd");
for (const [ad, sira] of PLAN) {
  const o = olc(sira);
  console.log(ad.padEnd(30) + g(o.test, 4) + g(o.sinif, 7) + g(v(o.sure, 1), 7) +
    g(o.sure <= BUTCE ? "sigar" : "asiyor", 8) + g(o.kacan, 7) + g(v(o.oran, 1), 8) + g(v(o.geri, 1), 9));
}

console.log("\ncikis olcutu taramasi: kapsanan sinif payi kac dakikaya mal olur");
console.log("olcut   gereken sinif   en ucuz sure   butce    kacan hata");
for (const p of [50, 60, 70, 80, 90]) {
  const gerek = Math.ceil((p / 100) * SINIF.length);
  if (gerek > TESTLER.length) { console.log(g("%" + p, 5) + g(gerek, 16) + g("ulasilamaz", 15) +
    g("-", 8) + g("-", 14)); continue; }
  const o = olc(ucuz.slice(0, gerek));
  console.log(g("%" + p, 5) + g(gerek, 16) + g(v(o.sure, 1), 15) +
    g(o.sure <= BUTCE ? "sigar" : "asiyor", 8) + g(o.kacan, 14));
}

const duman = TESTLER[0].dk + TESTLER[1].dk, ps = olc(sigan).sure;
let y = 4242;                                                       // TS7: aday tohumu
const kirmizi = Array.from({ length: ADAY }, () =>
  (y = (1103515245 * y + 12345) % 2147483648) / 2147483648 < 0.25).filter(Boolean).length;
console.log(`\ngiris olcutu: duman testi (T01+T02, ${v(duman)} dk) yesil degilse P2 kosmaz`);
console.log(`${ADAY} surum adayi, tohum 4242: ${kirmizi} aday duman testinde kirmizi`);
console.log(`olcutsuz  P2 ${ADAY} kez kosar ${v(ADAY * ps, 1)} dk; ${kirmizi} kosum bilgi uretmez -> bosa ${v(kirmizi * ps, 1)} dk`);
console.log(`olcutlu   P2 ${ADAY - kirmizi} kez kosar ${v((ADAY - kirmizi) * ps, 1)} dk + duman ${v(ADAY * duman, 1)} dk = ${v((ADAY - kirmizi) * ps + ADAY * duman, 1)} dk`);

console.log(`\nkacan hata kati TS5'in duyarliligi: ${ADAY} surumluk toplam bedel (dk)`);
console.log("kat   P1 tam kapsam   P2 butceye sigan   P3 olcutlu   en ucuz plan");
for (const kat of [2, 6, 20]) {
  const b = PLAN.slice(0, 3).map(([, s]) => { const o = olc(s); return ADAY * o.sure + kat * o.duzeltme; });
  const ad = ["P1", "P2", "P3"];
  console.log(g(kat, 3) + g(v(b[0], 0), 15) + g(v(b[1], 0), 19) + g(v(b[2], 0), 13) +
    g(ad[b.indexOf(Math.min(...b))], 10));
}
test envanteri — bedel nicelikleri M21/K03 ve M21/K04 kapanis tablolarindan
kod  test                      seviye        kosum  insan  toplam  sinif            sahip
T01  birim testi kumesi        birim         0,05    0,0    0,05  kural-siniri     gelistirme
T02  tumlesim testi            tumlesim      0,65    0,0    0,65  sema-uyusmazligi gelistirme
T03  veritabani goc testi      tumlesim      0,50    0,0    0,50  goc-veri-kaybi   gelistirme
T04  sozlesme testi            sozlesme      1,02    0,0    1,02  sozlesme-alani   gelistirme
T05  uctan uca tarayici testi  uctan-uca     4,30    0,0    4,30  arayuz-durumu    test
T06  gorsel dogrulama          uctan-uca     0,66    6,0    6,66  gorsel-sapma     test
T07  yuk testi                 basarim      15,50    0,0   15,50  veri-buyumesi    test
T08  statik guvenlik taramasi  guvenlik      0,02   42,0   42,02  sql-birlestirme  guvenlik
T09  bagimlilik taramasi       guvenlik      0,00   30,0   30,00  bilinen-acik     guvenlik
T10  erisilebilirlik denetimi  guvenlik      0,00   36,0   36,00  erisilebilirlik  urun
T11  hata enjeksiyonu          dayaniklilik  0,50   30,0   30,50  bozulmus-yanit   isletme
T12  kurtarma dogrulamasi      dayaniklilik  1,00   60,0   61,00  kurtarma-eksigi  isletme
toplam                                       24,21  204,0  228,21  12/14 sinif

kusur kumesi: tohum 20260731, 60 kusur, 14 sinif
hicbir testin gormedigi sinif: senaryo-disi (4), anlam-sapmasi (6)

plan karsilastirmasi — butce TS3 = 120 dk/surum, ufuk TS6 = 20 surum
plan                          test  sinif   sure   butce  kacan  kacak%  geri bd
P1 tam kapsam                   12     12  228,2  asiyor     10    16,7     40,8
P2 butceye sigan (olcutsuz)      9      9   89,2   sigar     18    30,0     16,5
P3 cikis olcutu >= %70          10     10  125,2  asiyor     14    23,3     26,0
P4 tam kapsam, 3 kalem sahipsiz   9      9  120,2  asiyor     20    33,3     13,7

cikis olcutu taramasi: kapsanan sinif payi kac dakikaya mal olur
olcut   gereken sinif   en ucuz sure   butce    kacan hata
  %50               7           28,7   sigar            24
  %60               9           89,2   sigar            18
  %70              10          125,2  asiyor            14
  %80              12          228,2  asiyor            10
  %90              13     ulasilamaz       -             -

giris olcutu: duman testi (T01+T02, 0,71 dk) yesil degilse P2 kosmaz
20 surum adayi, tohum 4242: 3 aday duman testinde kirmizi
olcutsuz  P2 20 kez kosar 1783,8 dk; 3 kosum bilgi uretmez -> bosa 267,6 dk
olcutlu   P2 17 kez kosar 1516,2 dk + duman 14,2 dk = 1530,4 dk

kacan hata kati TS5'in duyarliligi: 20 surumluk toplam bedel (dk)
kat   P1 tam kapsam   P2 butceye sigan   P3 olcutlu   en ucuz plan
  2           5974               4424         4544        P2
  6           8794               9704         8624        P3
 20          18664              28184        22904        P1

Bütün sayılar belirlenimlidir: aynı tohum aynı kusur kümesini verir. Envanterin ilk okuması bir dengesizliği gösteriyor — 228,21 dakikalık planın 204’ü insan zamanıdır; en pahalı üç kalem (T12, T08, T10) neredeyse tümüyle elle inceleme adımlarıdır.

İki Dağıtım, İki Sonuç

P1 bütün kusur sınıflarını kapsar ve sürüm başına 228,2 dakika ister — bütçeyi 108,2 dakika aşar. P2 aynı bütçeye sığmak için en ucuz testleri sırayla alır; dokuz test, 89,2 dakika. Bu iki dağıtımın aynı kusur kümesi üzerindeki sonucu farklıdır: P1’de 10 kusur kaçar (%16,7), P2’de 18 kusur kaçar (%30,0). Buna karşılık P2’nin geri bildirim süresi 16,5 dakikadır, P1’inki 40,8 — çünkü P1’in ucundaki pahalı kalemler yakaladıkları kusuru geç haber verir. Bir dağıtım kaçan hatayı azaltırken geri bildirim süresini uzatır. Bu kursun bütün derslerinde tekrarlanan takas budur.

Kaçan hatanın bedeli TS5’e bağlıdır ve bu varsayım ölçülmemiştir; duyarlılık taraması bunu görünür kılar. Kat 2 iken en ucuz plan P2, kat 6 iken P3, kat 20 iken P1’dir. Yani planın gerekçesi tek bir varsayımın değerine bağlıdır — ama üç planın yalnız biri, P2, bütçeye sığar. Bütçe bir maliyet kalemi değil, bir sınırdır.

Çıkış Ölçütünün Tavanı

Çıkış ölçütü taraması ölçütü bir fiyatla eşler. %50’lik bir ölçüt 28,7 dakikaya, %60 89,2 dakikaya mal olur ve ikisi de bütçeye sığar. TS4’ün seçtiği %70 ise 125,2 dakika ister — bütçeyi 5,2 dakika aşar. Ölçüt ile bütçe çelişir ve planın birini seçmesi gerekir.

%90 satırı ayrı bir şey söyler: ulaşılamaz. On dört sınıfın on ikisini gören test var, ikisini gören yok; hiçbir bütçe bu tavanı kaldırmaz, çünkü tavan zamandan değil kapsamdan gelir. Plan bu iki sınıfı ya kapsam dışı diye açıkça yazar ya da onları görecek bir sınama biçimi ekler. Kapsam dışının ürettiği kaçan hata bu kümede 10 kusurdur.

Giriş Ölçütü ve Sorumluluk

Giriş ölçütü koşumun kendisini değil, koşumun ne zaman başlayacağını düzenler. Duman testi (T01 ile T02, 0,71 dakika) yeşil değilken P2’yi koşturmak yirmi adayda 267,6 dakikayı bilgi üretmeyen koşumlara harcar. Ölçüt konduğunda duman testinin yirmi kez koşması 14,2 dakika tutar ve toplam 1.530,4 dakikaya iner — 253,4 dakikalık bir kazanç, ucuz bir yoklamanın pahalı bir aşamayı koruması.

Sorumluluk sütunu planın en sessiz sütunudur. P4, P1 ile aynı kapsamı yazar ama üç kalemin sahibi ekip dışındadır ve o kalemler koşmaz. Kâğıtta 12 sınıf kapsanır, gerçekte 9; kaçan hata 10’dan 20’ye çıkar ve kaçak oranı %33,3 olur — bütçeye sığan ölçütsüz plandan daha kötü bir sonuç, üstelik plan tam kapsam iddiasındayken. Sahibi yazılmamış kalem kapsamda değildir.

Kırmızı sonucun ne yaptığı da plana yazılır: T01–T05 kırmızıya döndüğünde sürüm adayı ilerlemez, T06 ile T10 sürümü durdurmadan bir kayıt açar, T12’nin kırmızısı işletmenin kararına girer. Hiçbir kararı değiştirmeyen test bütçeden pay almamalıdır.

Özet

  • Test planı üç sütundur: kapsam, ölçüt ve sorumluluk; üçü de sayıya bağlanmadan plan karar taşımaz.
  • Dört kursun on iki testi 228,21 dakikadır ve bunun 204’ü insan zamanıdır; bütçe (TS3) 120 dakika olduğu için tam kapsam bir plan değil bir istektir.
  • Aynı kusur kümesinde tam kapsam 10 kusur kaçırıp 40,8 dakikada haber verir; bütçeye sığan plan 18 kusur kaçırıp 16,5 dakikada haber verir.
  • Çıkış ölçütü bir fiyatla gelir: %70 ölçütü bütçeyi aşan 125,2 dakika ister, %90 hiçbir bütçeyle ulaşılamaz çünkü iki kusur sınıfını hiçbir test görmez.
  • Giriş ölçütü ucuz bir yoklamayı pahalı aşamanın önüne koyar: 267,6 dakikalık boşa koşum 14,2 dakikalık duman testiyle önlenir.
  • Sahipsiz üç kalem tam kapsamlı planı dokuz teste indirir, kaçak oranını %16,7’den %33,3’e çıkarır.

Sonraki Adım

Bütçeye sığan plan testleri en ucuzdan seçti; bu sıralamanın tek gerekçesi bütçeye çok kalem sığdırmaktı. Oysa kusur kümesindeki her kusurun bir olasılığı ve bir etkisi var, ve ucuzluk bunların ikisiyle de ilgili değil. Aynı 120 dakika başka bir sırayla dağıtılsaydı kaç kusur yakalanırdı? Sonraki ders sıralamayı bir karar hâline getirir: olasılık ile etkinin çarpımına göre seçilen alt küme, rastgele seçilenle, en ucuz önce seçilenle ve en çok kod dokunanı önce seçenle aynı bütçede karşılaştırılır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat