Ders 10 / 12
Test Senaryosu Yazımı
Bir test senaryosunun kimlik, ön koşul, adım ve beklenen sonuç parçaları, iyi senaryonun ölçütleri ve yazılı senaryodan çalıştırılabilir teste geçiş.
İçindekiler
Teknikler hangi girdilerin deneneceğini belirledi. Denenen şeyin bir başkasına anlatılabilmesi ayrı bir iştir: hangi durumda başlanacak, hangi adımlar izlenecek, ne gözlenecek? Otomatik denetim bu bilgiyi kodun içinde taşır ve yalnız kodu okuyan kişiye anlatır. Kütüphane görevlisinin, gözden geçiren kişinin ya da kuralı yazan çözümleyicinin okuyabileceği bir biçim gerekir.
Bu ders o biçimi kurar ve biçimden çalıştırılabilir teste geçişi gösterir.
Senaryonun Parçaları
Bir test senaryosu (test case) altı parçadan oluşur.
Kimlik senaryoya sabit bir numara verir; hata kaydı ve gerileme kümesi bu numaraya atıf yapar. Başlık senaryonun ne sınadığını tek cümlede söyler ve beklenen sonucu içerir — başlığı okuyan kişi testin niyetini anlar.
İzlenebilirlik bağı senaryonun hangi kuraldan geldiğini gösterir. Birinci derste kurulan süreç kalitesi ölçümü tam olarak bu bağa dayanır: hangi kuralın senaryosu var, hangisinin yok?
Ön koşul (precondition) senaryonun başlayabilmesi için sistemin hangi durumda olması gerektiğini yazar. Ön koşul eksikse senaryo tekrarlanabilir olmaz; iki koşuda iki farklı sonuç verir.
Adımlar yapılacak işi sırayla verir. Bir senaryonun tek bir amacı olduğu için adım sayısı azdır; uzun adım listesi çoğu zaman birden çok senaryonun birbirine yapışmış hâlidir.
Beklenen sonuç (expected result) gözlenecek şeyi yazar. Gözlenebilir olmalıdır: ekranda görünen, dönen değer, kaydedilen satır. “Sistem doğru davranır” gözlenebilir bir sonuç değildir.
Bunlara son koşul eklenebilir: senaryo bittiğinde sistemin hangi durumda kalacağı. Son koşul yazılıysa senaryolar birbirinin kurduğu duruma bağımlı kalmaz.
İyi Senaryonun Ölçütleri
Aynı kuralı sınayan iki senaryo yazımı karşılaştırılabilir. Zayıf yazım şöyledir: “Borçlu üye ödünç almaya çalışır, sistem uygun tepkiyi verir.” Bu cümlenin üç kusuru vardır. Borcun ne kadar olduğu yazılı değil, bu yüzden ön koşul belirsiz. Sınırın altında mı üstünde mi olduğu bilinmiyor, bu yüzden hangi denklik sınıfını temsil ettiği belirsiz. “Uygun tepki” gözlenebilir bir sonuç değil, bu yüzden senaryo geçti mi kaldı mı kararı okuyan kişiye kalıyor.
Güçlü yazım aynı kuralı şöyle sorar: ön koşul “borcu tam 20 birim olan bir üye, bir aktif ödüncü var”, adım “üye rafta duran bir kitabı ödünç almak ister”, beklenen sonuç “istek reddedilir ve gerekçe olarak borç sınırı gösterilir”.
Ölçütler dört başlıkta toplanır. Tek amaç: bir senaryo bir kuralı sınar; iki kural iki senaryodur, çünkü düştüğünde hangisinin bozulduğu belli olmalıdır. Belirlenimcilik: aynı ön koşulla aynı sonucu verir; bugünün tarihine, rastgele değere ya da sıraya bağlı değildir. Bağımsızlık: başka bir senaryonun bıraktığı duruma dayanmaz. Gözlenebilirlik: sonuç bakılarak karar verilebilecek bir şeydir.
Senaryolar Veri Olarak
Senaryo yapısı düzenliyse veri olarak temsil edilebilir. Bu temsil iki kazanç sağlar: senaryolar okunabilir kalır ve aynı listeden hem rapor hem çalıştırılabilir test üretilir.
// karar.mjs — sinir kusuru giderilmis odunc karari export const ODUNC_SINIRI = { ogrenci: 10, uye: 5 }; export const BORC_SINIRI = 20; export function oduncKarari({ uyeTuru, aktifOdunc, borc, baskasinaRezerve }) { if (!(uyeTuru in ODUNC_SINIRI)) throw new Error(`bilinmeyen uye turu: ${uyeTuru}`); if (baskasinaRezerve) return 'rezerve'; if (borc >= BORC_SINIRI) return 'borc'; if (aktifOdunc >= ODUNC_SINIRI[uyeTuru]) return 'sinir'; return 'verildi'; }
// senaryolar.mjs — yazili senaryolarin veri olarak temsili export const KURALLAR = ['K3', 'K4', 'K13', 'K14', 'K15']; export const SENARYOLAR = [ { no: 'TS-01', kural: 'K4', baslik: 'Odunc siniri dolan uyeye yeni kitap verilmez', onKosul: { uyeTuru: 'uye', aktifOdunc: 5, borc: 0, baskasinaRezerve: false }, adim: 'Uye rafta duran bir kitabi odunc almak ister', beklenen: 'sinir', }, { no: 'TS-02', kural: 'K13', baslik: 'Borcu sinira ulasan uyeye kitap verilmez', onKosul: { uyeTuru: 'uye', aktifOdunc: 1, borc: 20, baskasinaRezerve: false }, adim: 'Uye rafta duran bir kitabi odunc almak ister', beklenen: 'borc', }, { no: 'TS-03', kural: 'K14', baslik: 'Baskasi adina rezerve kitap verilmez', onKosul: { uyeTuru: 'ogrenci', aktifOdunc: 0, borc: 0, baskasinaRezerve: true }, adim: 'Ogrenci rezerve listesindeki kitabi odunc almak ister', beklenen: 'rezerve', }, { no: 'TS-04', kural: 'K3', baslik: 'Siniri dolmamis ogrenciye kitap verilir', onKosul: { uyeTuru: 'ogrenci', aktifOdunc: 9, borc: 0, baskasinaRezerve: false }, adim: 'Ogrenci rafta duran bir kitabi odunc almak ister', beklenen: 'verildi', }, { no: 'TS-05', kural: 'K3', baslik: 'Odunc siniri dolan ogrenciye yeni kitap verilmez', onKosul: { uyeTuru: 'ogrenci', aktifOdunc: 10, borc: 0, baskasinaRezerve: false }, adim: 'Ogrenci rafta duran bir kitabi odunc almak ister', beklenen: 'sinir', }, ];
Listeyi koşturan sürücü aynı zamanda izlenebilirlik raporunu üretir.
// senaryo-kosucu.mjs — senaryolarin kosturulmasi ve izlenebilirlik raporu import { oduncKarari } from './karar.mjs'; import { SENARYOLAR, KURALLAR } from './senaryolar.mjs'; let uyusan = 0; for (const s of SENARYOLAR) { const gozlenen = oduncKarari(s.onKosul); const sonuc = gozlenen === s.beklenen ? 'uyustu' : `SAPMA (gozlenen ${gozlenen})`; console.log(`${s.no} [${s.kural}] ${sonuc}: ${s.baslik}`); if (gozlenen === s.beklenen) uyusan += 1; } const kapsanan = new Set(SENARYOLAR.map((s) => s.kural)); const senaryosuz = KURALLAR.filter((k) => !kapsanan.has(k)); console.log(`sonuc: ${uyusan}/${SENARYOLAR.length} senaryo uyustu`); console.log(`izlenebilirlik: ${KURALLAR.length} kuraldan ${kapsanan.size} tanesinin senaryosu var`); console.log(`senaryosuz kural: ${senaryosuz.join(', ')}`);
TS-01 [K4] uyustu: Odunc siniri dolan uyeye yeni kitap verilmez TS-02 [K13] uyustu: Borcu sinira ulasan uyeye kitap verilmez TS-03 [K14] uyustu: Baskasi adina rezerve kitap verilmez TS-04 [K3] uyustu: Siniri dolmamis ogrenciye kitap verilir TS-05 [K3] uyustu: Odunc siniri dolan ogrenciye yeni kitap verilmez sonuc: 5/5 senaryo uyustu izlenebilirlik: 5 kuraldan 4 tanesinin senaryosu var senaryosuz kural: K15
Beş senaryonun beşi de uyuştu, ama son satır birinci dersteki uyarıyı tekrarlar: şube dışı iade kuralının hiçbir senaryosu yok. Senaryo listesi yazılı olduğu için bu boşluk sayılabilir bir büyüklüğe dönüşmüştür.
Senaryodan Çalıştırılabilir Teste
Aynı liste, koşucuya verilecek testleri de üretebilir. Aşağıdaki blok senaryo listesini gezerek her senaryo için bir test tanımlar ve Node’un yerleşik koşucusuyla çalıştırır. Çıktıdaki süre alanları ortama bağlı olduğu için yalnız sayım satırları süzülür.
cat > senaryo.test.mjs <<'EOF' import test from 'node:test'; import assert from 'node:assert/strict'; import { oduncKarari } from './karar.mjs'; import { SENARYOLAR } from './senaryolar.mjs'; for (const s of SENARYOLAR) { test(`${s.no} ${s.baslik}`, () => { assert.equal(oduncKarari(s.onKosul), s.beklenen); }); } EOF node --test senaryo.test.mjs 2>&1 | grep -E '^ℹ (tests|pass|fail) '
ℹ tests 5 ℹ pass 5 ℹ fail 0
Geçiş üç eşleştirmeden ibarettir: ön koşul kurulum verisine, adım çağrıya, beklenen sonuç iddiaya karşılık gelir. Senaryo bu üç parçayı taşımıyorsa çalıştırılabilir teste çevrilemiyor demektir — ve çevrilemiyorsa elle koşturulduğunda da aynı belirsizliği taşır.
Test adının senaryo numarasıyla başlaması bilinçlidir. Bir test düştüğünde okunacak ilk şey hangi senaryonun bozulduğudur; numara, hata kaydından senaryoya ve senaryodan kurala giden yolu açık tutar.
Elle Koşturulan Senaryonun Yeri
Her senaryo otomatik teste çevrilmez. Kütüphane görevlisinin ekrandaki yerleşimi anlaşılır bulup bulmadığı, bir uyarı metninin yeterince açık olup olmadığı yazılı senaryoyla sınanır ama insan yargısı gerektirir.
Ayrı bir tür daha vardır: keşif testi (exploratory testing). Burada senaryo önceden yazılmaz; sınayan kişi ürünü kullanırken bir sonraki denemesini bir öncekinin sonucuna göre seçer. Keşif testi yazılı senaryonun yerine geçmez, onun boşluğunu doldurur — dördüncü derste anılan sormayı unutulan soru çoğu zaman böyle bulunur. Bulunduğunda ise yazılı bir senaryoya çevrilir ve gerileme kümesine katılır.
Özet
- Test senaryosu kimlik, başlık, izlenebilirlik bağı, ön koşul, adımlar ve beklenen sonuçtan oluşur; son koşul senaryoları birbirinden bağımsız kılar.
- İyi senaryonun ölçütleri tek amaç, belirlenimcilik, bağımsızlık ve gözlenebilir sonuçtur; “sistem uygun tepkiyi verir” gözlenebilir bir sonuç değildir.
- Senaryolar veri olarak temsil edildiğinde aynı listeden hem izlenebilirlik raporu hem çalıştırılabilir test üretilir.
- Senaryodan teste geçiş üç eşleştirmedir: ön koşul kuruluma, adım çağrıya, beklenen sonuç iddiaya karşılık gelir.
- Örnekte beş senaryonun beşi uyuştu, ama beş kuraldan birinin hiç senaryosu olmadığı sayılabilir biçimde ortaya çıktı.
- Keşif testi yazılı senaryonun yerine geçmez; bulduğu şey yazılı senaryoya çevrilerek gerileme kümesine katılır.
Sonraki Adım
Senaryonun en kritik alanı sessizce geçildi: beklenen sonuç nereden geliyor? Yukarıdaki beş senaryoda değerler belirtimden okundu, çünkü kural yazılıydı. Kural yazılı değilse, hesap elle doğrulanamayacak kadar karmaşıksa ya da doğru sonucu kimse bilmiyorsa beklenen sonuç nasıl belirlenir? Sonraki ders bu soruyu ele alır ve beklenen sonucun kaynağını üç ayrı yöntemle kurup karşılaştırır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.