Kısım II · İnşaat · Bölüm 42
Test ve Kalite
Değişiklikleri kanıtla denetlemek (Testing and code quality)
Neden burada: Bölüm 41: Kimlik Doğrulama ve Güvenlik veri ve erişim kurallarını koydu. Ama kuralı bugün doğru yazmak yetmez; yarınki değişiklik onu bozabilir. Bu bölüm bir değişikliğin neyi koruduğunu çalıştırılabilir beklentilere çevirmeyi anlatır.
Neye dayanıyor: Bölüm 27: Modüler Kod içindeki bağımsız modüller ve puan fonksiyonu; Bölüm 30: TypeScript içindeki tip denetiminin sınırı; Bölüm 37: Go ile API Yazmak içindeki işleyici, servis ve depo ayrımı. Testleri bu sınırların üzerine kuracağız, yeni bir programlama dili öğretmeyeceğiz.
- Kat 10Bizim uygulamamızİş kuralları, HTTP sınırları ve kullanıcı akışı için otomatik denetimler. Testler de Kat 7'nin süreçleri ve Kat 3'ün işlemcisi üzerinde çalışan programlardır. Kat planına dön.
- Kat 9Web ve tarayıcıWeb istemcisi sunucunun sözleşmesini kullanır.
- Kat 8Ağ ve internetHTTP istekleri, DNS ve TLS; parçalar ayrı makinelerdeyken aradaki yol.
- Kat 7İşletim sistemiSüreçler, dosyalar ve izinler; altta Kat 3'ün işlemcisi ve belleği.
Bölüm sonunda bir testin hangi parçaları gerçekten sınadığını söyleyebilecek, Go ve JavaScript test dosyasını okuyabilecek, testin geçmesiyle ürünün doğru olması arasındaki sınırı açıklayabileceksin. Önce testin kapsamını, sonra yazım ritmini, ardından gerçek küçük örnekleri ve ortak denetim hattını kuracağız.
42.1 Birim, entegrasyon ve uçtan uca testler
“Uygulama çalışıyor” cümlesi tek bir iddia gibi görünür. Oysa içinde çok sayıda ayrı iddia saklıdır: puan kuralı doğru mu, gelen JSON doğru çözülüyor mu, SQL doğru satırı mı değiştiriyor, kullanıcı düğmeye dokununca yeni puanı görüyor mu? Test (test), belirli bir koşulda belirli bir davranışı denetleyen düzenektir. Otomatik testte başka bir program, denenecek kodu çalıştırıp gözlediği sonucu beklenen sonuçla karşılaştırır. O da aynı işlemciyi, belleği ve dosyaları kullanır; uygulamanın yanına konmuş doğaüstü bir doğruluk makinesi değildir.1
Önce Bölüm 27: Modüler Kod içindeki öğretim amaçlı puan kuralını geri alalım: yanlış cevaba sıfır, doğru cevaba temel puan, yeterli seride ek puan. Bu örnek gerçek ürünün kararlaştırılmış oyun kuralı değildir; aynı küçük parçayı birden çok bölümde takip etmek için kullanıyoruz. Kuralı ekran kodundan ayırdığımız için artık onu ekrana dokunmadan sınayabiliriz. Modülerliğin somut kazancı burada görünür: küçük arayüz, bağımsız denenebilen gerçekleme.1
Testin iskeleti: hazırla, çalıştır, karşılaştır
Bir testte üç soruya cevap aranır. Başlangıç durumu nedir? Hangi eylem yapılacak? Eylemden sonra ne gözlenecek? “Doğru cevap, seri eşiğinin hemen altında” bir başlangıçtır; puan fonksiyonunu çağırmak eylemdir; temel puan dönmesini beklemek gözlemdir. Doğrulama ifadesi (assertion), bu beklentiyi çalıştırılabilir karşılaştırma haline getirir. Testin sadece çökmemesi değil, yanlış sonuçta açıkça başarısız olması gerekir.12
| Test düzeyi | Bizim örneğimiz | Ne çalışır? | Tek başına neyi göstermez? |
|---|---|---|---|
| Birim | Seri eşiğinde verilen puan | Küçük bir mantık parçası | SQL ve gerçek ağ davranışını |
| Entegrasyon | Cevap kaydıyla puan güncellemesinin birlikte onaylanması | Go veri erişimi ve test Postgres'i | Telefon ekranının güncellendiğini |
| Uçtan uca | Giriş yap, soruyu cevapla, puanı ekranda gör | İstemci, API ve gerekli gerçek servisler | Denemediğimiz bütün durumların doğruluğunu |
Tablo, Practical Test Pyramid yazısındaki kapsam ayrımını hukuk uygulamamıza uyarlayan bir tasarım örneğidir. Adlandırmalar ekipten ekibe değişebilir; bir testin adından çok hangi sınırları gerçekten geçtiğine bakılır.1
Birim testi: küçük ve dar bir iddia
Birim testi (unit test), sınırlı bir kod biriminin davranışını sınar. Birim bazen tek fonksiyon, bazen birbiriyle yakın çalışan birkaç parçadır; “her fonksiyona ayrı test” gibi evrensel bir sayım kuralı yoktur. Ama dış servis olmadan puan hesabını deneyebilmek hata yerini daraltır. Yanlış sonucu gördüğünde önce DNS'i, TLS sertifikasını ve Postgres parolasını araştırmak zorunda kalmazsın.1
Seçeceğimiz örnekler yalnızca alışıldık durumlar olmamalı. Seri bonusu bir eşikte başlıyorsa eşiğin hemen altı, tam kendisi ve hemen üstü özellikle öğreticidir. Yanlış cevap, bonus koşulu sağlansa bile sıfır vermelidir. Bunlar sınır durumu (edge case) denetimleridir: programın yol ayrımında bir küçük karşılaştırma hatası büyük davranış değişikliğine dönüşebilir. “Yeterince çok rastgele örnek yazdım” ile “önemli dalları düşündüm” aynı şey değildir.19
Entegrasyon testi: iki parça gerçekten anlaşabiliyor mu?
Entegrasyon testi (integration test), parçalar arasındaki gerçek ilişkiyi denetler. Go'nun verdiği SQL parametresi Postgres'te doğru veri tipine gidiyor mu? Cevap kaydı başarısız olduğunda puan güncellemesi de geri alınıyor mu? Bunları yalnızca bellekteki sahte bir depo ile kanıtlayamayız. Gerçek veritabanı davranışını sınamak için testin kontrol ettiği ayrı bir veritabanı gerekir.1
Bölüm 39: Postgres Pratikte içindeki işlem ve benzersizlik kısıtını test senaryosuna çevirelim. Başlangıçta kurgu bir kullanıcı oluşturulur. Bir cevap gönderilir; cevap kaydı ve puan birlikte okunur. Aynı iş tekrar gönderilir; ürün kuralı tek ödül diyorsa ikinci kez ödül verilmediği denetlenir. Başka bir senaryoda ikinci SQL adımını başarısız kılacak koşul hazırlanır; ilk adımın da kalıcılaşmadığı kontrol edilir. Burada beklenen sonuç, uygulamanın vaat ettiği sözleşmeden gelir; test onu kendiliğinden keşfetmez.1
Test verisi düzeneği (fixture), test için hazırlanan bilinen başlangıç verisidir. Testler birbirinin bıraktığı kullanıcıya veya önceki çalışmanın puanına muhtaç olmamalıdır. Yalıtım ve temizleme düzeni kurulmazsa bir test tek başına geçer, ötekinden sonra kalır. Test veritabanı üretim veritabanından ayrı olmalıdır; adı “test” olan bir betiğin yanlış bağlantıyla üretime yazması teknik olarak mümkündür. Ortam ayrımını Bölüm 43: Yayına Alma ve Bulut içinde genişleteceğiz.1
Sahte gerçekleme neyi satın alır, neyi satın alamaz?
Test dublörü (test double), gerçek işbirlikçinin yerine testte kullanılan parçadır. Örneğin bir depo arayüzünün bellekte çalışan sahte gerçeklemesi, servisin “kullanıcı yok” hatasına nasıl davrandığını hızlıca denememizi sağlar. Bazı dublörler önceden belirlenmiş yanıt verir; bazıları kendilerine yapılan çağrıları kaydeder. Bunları gündelik dilde topluca “mock” diye duyabilirsin; önemli olan değiştirdiğimiz sınırın farkında olmaktır.1
Sahte depo SQL sözdizimini, gerçek kısıtları, işlem yalıtımını ve bağlantı hatalarını aynı biçimde yaşamaz. Bu nedenle “sahte depoyla geçti” sonucu “Postgres'le de kesin çalışır” sonucuna dönüşmez. Diğer yandan her küçük iş kuralı için gerçek Postgres başlatmak da gereksiz yavaşlık ve kurulum yükü getirebilir. Küçük davranışı dar testte, gerçek bağlantıyı entegrasyon testinde sınamak iki ayrı güvenceyi birleştirir.1
Uçtan uca test: kullanıcının yolculuğu
Uçtan uca test (end-to-end test, E2E), anlamlı bir kullanıcı akışını birden çok katman boyunca sınar. Web sürümünde tarayıcı açılır, kurgu hesapla giriş yapılır, soru cevaplanır ve ekranda beklenen sonuç aranır. Playwright gibi araçlar bu akışın tarayıcı tarafını otomatikleştirebilir. Burada web tarayıcısı testinden söz ediyoruz; mobil tarayıcı benzetimi, Expo'nun yerel Android/iOS uygulamasının gerçekten çalıştırılmasıyla aynı test değildir.18
Bu geniş kapsam, başarısızlığın kaynağını bulmayı da güçleştirir. Beklenen metin görünmediyse iş kuralı mı yanlış, ağ mı kopuk, veri mi hazırlanmamış, düğme mi değişmiş? Kararsız test (flaky test), aynı kodla bazen geçip bazen kalan testtir. Sabit süre uyumak yerine beklenen koşulu beklemek, veriyi denetlemek ve dış bağımlılıkları sınırlamak kararsızlığı azaltmaya yardım eder. Testi sebebini araştırmadan tekrar çalıştırıp yeşile boyamak ise güven üretmez.1
Test piramidi (test pyramid), çok sayıda dar ve hızlı denetim, daha az geniş ve pahalı denetim fikrini hatırlatan bir benzetmedir; zorunlu oran tablosu değildir. Ham Vocke'nin Practical Test Pyramid yazısı da terimlerin ve basit üçgenin sınırlarını belirtir. Bizim ürünümüzde kritik giriş ve cevap akışları birkaç E2E senaryosuyla, puan ve erişim kuralları çok sayıda küçük örnekle korunabilir. Sayıları uygulamanın riski ve geri bildirim süresi belirler.1
Bölüm 41: Kimlik Doğrulama ve Güvenlik içindeki “A, B'nin geçmişini okuyamaz” kuralını birim düzeyinde yetki kararıyla, entegrasyon düzeyinde gerçek sorgunun kullanıcı kapsamıyla, uçtan uca düzeyinde iki kurgu hesapla sınayabiliriz. Üç test birbirinin kopyası değildir: biri karar mantığını, biri veri sınırını, biri bütün akışı korur. Prototipinin mevcut testlerini görmedik; bu bir önerilen test haritasıdır.19
42.2 Test önce geliştirme fikri
Test önce geliştirme (test-driven development, TDD), yeni davranışı önce bir testle ifade edip kodu küçük adımlarla bu beklentiye yaklaştırma yöntemidir. Fowler'ın özetlediği döngü kırmızı → yeşil → yeniden düzenle biçimindedir. Kırmızıda istenen davranış henüz yoktur ve test başarısızdır. Yeşilde o davranışı sağlayan kod yazılır. Son adımda testlerin koruması altında yapı sadeleştirilir.3
Neden önce başarısızlığı görmek isteriz? Test gerçekten ilgili hatayı yakalayabiliyor mu, onu öğreniriz. Test baştan geçiyorsa belki davranış zaten vardır; belki yanlış fonksiyon çağrılmıştır; belki hiçbir beklenti denetlenmemiştir. Fakat her kırmızı sonuç da iyi değildir. Dosyanın derlenmemesi veya veritabanı parolasının yanlış olmasıyla “seri eşiğinde bonus verilmedi” aynı geri bildirim değildir. Başarısızlığın beklediğin nedenle oluştuğunu okumalısın.39
Puan kuralında küçük bir döngü
Öğretim örneğimizde seri eşiği 7, temel puan 10, bonus 5 olsun. “Doğru cevap, seri 7: sonuç 15” testini önce yazarız. İlk gerçekleme eşiği yanlışlıkla seri >= 8 kabul ediyorsa test 10 görür ve başarısız olur. Eşiği 7 yaptığımızda test geçer. Sonra eşiğin altı ve üstü ile yanlış cevap örneklerini ekleyebiliriz. Bu sayılar ürün tavsiyesi değil, Bölüm 27: Modüler Kod ile aynı örneği izleyen hesap değerleridir; sonuçlar Python ile de doğrulandı.
Yeniden düzenleme (refactoring), gözlenebilir davranışı değiştirmeden iç yapıyı iyileştirmektir. “Bonus hesabını daha açık isimli bir fonksiyona ayırdım” bu olabilir; “artık bonus iki kat” ise davranış değişikliğidir ve yeni beklenti gerektirir. TDD'nin son adımı atlanırsa test geçen fakat giderek zor anlaşılan bir kod yığını da oluşabilir. Test, tasarım düşüncesini gereksiz kılmaz.3
Bu yöntemin tasarımla bağı Bölüm 1: Büyük Harita içindeki arayüz–gerçekleme ayrımıdır. Henüz kodu yazmadan “bu fonksiyona ne veririm, karşılığında ne beklerim?” diye düşünürsün. Puanı test etmek için tarayıcı, oturum, Postgres ve e-posta sunucusu kurman gerekiyorsa küçük iş kuralının sınırı belki yeterince ayrılmamıştır. Test yazmanın zorluğu bazen test aracının değil tasarımın geri bildirimidir.31
Yanlış ürün kuralını testte de yanlış beklersen kodla test birlikte yeşil olur. Ayrıca keşif gerektiren her çalışma aynı ritimde ilerlemeyebilir. Buradaki amaç bir yöntemi zorunlu ilan etmek değil, önce davranışı somutlaştırmanın ve hatayı küçük adımda yakalamanın mantığını anlamak. Hata düzeltirken de hatayı yeniden üreten bir test yazıp düzeltmeden sonra geçtiğini görmek, hatanın geri gelmesini önlemeye yardım eder.39
42.3 Go'da go test, JavaScript'te test araçları
Go'da temel test desteği standart araç zincirindedir. testing paketi test işlevlerine denetim araçları verir; go test test dosyalarını derleyip çalıştırır. _test.go ile biten dosya normal paket derlemesinin parçası değildir; test çalışmasında dahil edilir. TestXxx(t *testing.T) biçimi aracın test fonksiyonunu tanımasını sağlar.24
Aşağıdaki bağımsız örnek bu bölüm için ayrı bir geçici klasörde çalıştırıldı. Projenizin mevcut Go dosyaları oldukları iddia edilmiyor. İlk dosya küçük iş kuralıdır; sonraki dosya aynı kuralın veri tablosuyla sınanmasıdır.
package puan
func Puan(dogru bool, seri int) int {
if !dogru {
return 0
}
if seri >= 7 {
return 15
}
return 10
}
package puan dosyanın paketini söyler. Puan, bir Boole ve bir tam sayı alıp tam sayı döndürür. İlk koşul yanlış cevabı erken bitirir. İkinci koşul doğru cevabı seri eşiğine göre ayırır. Son dönüş, bonus almayan doğru cevabın sonucudur. Bu örnekte geçerli, negatif olmayan seri değerlerinin çağıran tarafta sağlandığı varsayılır; giriş doğrulama testleri ayrıca gerekir.
package puan
import "testing"
func TestPuan(t *testing.T) {
durumlar := []struct {
ad string
dogru bool
seri int
beklenen int
}{
{"esik_alti", true, 6, 10},
{"tam_esik", true, 7, 15},
{"esik_ustu", true, 8, 15},
{"yanlis_cevap", false, 7, 0},
}
for _, d := range durumlar {
t.Run(d.ad, func(t *testing.T) {
alinan := Puan(d.dogru, d.seri)
if alinan != d.beklenen {
t.Errorf("alinan=%d beklenen=%d", alinan, d.beklenen)
}
})
}
}
import "testing" standart paketi alır. TestPuan testin giriş noktasıdır. durumlar her satırda ad, iki girdi ve beklenen sonucu tutan bir dilimdir; bu, tablo güdümlü test (table-driven test) biçimidir. Döngü satırları gezer. t.Run her satırı adlandırılmış alt test olarak çalıştırır. alinan gerçek fonksiyon sonucudur; if onu beklentiyle karşılaştırır. t.Errorf uyuşmazlığı kaydederek testi başarısız yapar; biçim metnindeki iki %d elde edilen ve beklenen tam sayıları yazar. Böylece “test kaldı” yerine hangi karşılaştırmanın kaldığını okuyabiliriz.2
go test -v ./...
go test -count=1 ./...
İlk komut mevcut modül altındaki paketlerin testlerini ayrıntılı çalıştırır. İkinci komut sonuç önbelleğinin yeniden kullanılmasını önleyerek testleri bir kez yeniden koşturmayı ister. Bu bölümün örneğinde dört alt test de geçti. Ardından yalnız öğretim kopyasında eşiği 8 yapıp aynı testi yeniden çalıştırdım: tam_esik alt testi alinan=10 beklenen=15 bildirerek kaldı. Eşiği geri düzelttikten sonraki çalışma yeniden geçti. Bu, testin en azından bu hatayı gerçekten yakaladığını gösterir; bütün olası hataları yakaladığını değil.4
HTTP işleyicisini gerçek port açmadan denemek
Bölüm 37: Go ile API Yazmak içindeki işleyiciye deneme isteği vermek için Go'nun net/http/httptest paketi kullanılabilir. NewRequest bir sunucu isteği oluşturur; NewRecorder yazılan yanıtı kaydeder. İşleyiciyi bunlarla çağırıp durum kodunu ve gövdesini okuyabiliriz. Bu test gerçek TCP/TLS bağlantısını sınamaz; denenen işleyici başka hangi parçaları gerçekten çağırıyorsa kapsamı odur.5
Örneğin bozuk JSON'a hatalı istek yanıtı dönüyor mu, oturumsuz istek reddediliyor mu, servis hatası istemciye sır sızdırmadan çevriliyor mu diye denetlenebilir. “HTTP testi” etiketi tek başına bunun birim mi entegrasyon mu olduğunu söylemez; sahte servis mi, gerçek Postgres mi kullanıldığına da bakmalısın. Test adında, kurulumunda ve açıklamasında kapsam görünür olmalıdır.15
JavaScript tarafında aynı mantık
JavaScript'te de ayrı bir test koşucusu gerekir. Node.js'in yerleşik node:test modülü, basit dil mantığını ek paket olmadan sınayabilir. Vite ile çalışan projelerde Vitest gibi araçlar; web tarayıcısı akışlarında Playwright gibi araçlar karşına çıkabilir. Birini seçmek ötekilerin yerini otomatik doldurmaz: saf fonksiyon testi, tarayıcı DOM'u ve yerel mobil ekran farklı çalışma ortamlarıdır.678
export function puanHesapla(dogru, seri) {
if (!dogru) return 0;
return seri >= 7 ? 15 : 10;
}
export fonksiyonu test dosyasına açar. İlk koşul yanlış cevabı ayırır. Son satır koşullu ifadeyle seri eşiğine göre iki doğru cevap sonucundan birini seçer. Dosyanın .mjs uzantısı bu bağımsız örneğin ES modülü olarak okunmasını sağlar.
import test from "node:test";
import assert from "node:assert/strict";
import { puanHesapla } from "./puan.mjs";
test("seri esiginde bonus", () => {
assert.equal(puanHesapla(true, 7), 15);
});
test("yanlis cevapta sifir", () => {
assert.equal(puanHesapla(false, 7), 0);
});
İlk içe aktarma test koşucusunu, ikincisi katı karşılaştırma aracını, üçüncüsü bizim fonksiyonu alır. Her test çağrısı adlandırılmış bir beklenti tanımlar. assert.equal gerçek sonuçla beklenen değeri karşılaştırır; eşit değillerse hata üreterek testi düşürür. Bağımsız klasörde node --test puan.test.mjs komutuyla bu iki test de çalıştırılıp geçti. Bu çalışma ekranı, Expo'yu veya Postgres'i denemedi; yalnızca gösterilen JavaScript mantığını denedi.6
Kapsama oranı ve rastlantı tuzağı
Test kapsamı (test coverage), çalıştırılan kod bölümleri hakkında ölçüm verir. Go'nun -cover seçeneği ifadelerin çalıştırılmasını ölçer; bir satırın çalıştırılmış olması sonucunun doğru denetlendiği anlamına gelmez. Beklenti yazmadan bütün satırları gezen test de yüksek kapsam gösterebilir. Bu yüzden kapsam raporunu “nereleri hiç denememişiz?” sorusu için kullanmak, onu doğruluk puanı saymaktan daha yararlıdır.49
Seri hesabı gibi tarihe bağlı mantıkta testin “bugün”ünü denetlemek gerekir. Gerçek saate doğrudan bağımlı bir test gece yarısında farklı sonuç verebilir; rastgele sırayla veri kullanan test bazen farklı başlangıç görür. Çözüm, sınırın ihtiyacına göre saati ya da veri kaynağını dışarıdan verilebilir kılmaktır. Testin tekrarlanabilir olması, üretimde zamanın ve ağın kusursuz olduğunu varsaymak değildir; belirli senaryoyu bilinen koşulda sınamaktır.1
42.4 Kod incelemesi ve sürekli entegrasyon ile bağ
Test, yazılmış beklentileri çalıştırır. İnsan ise beklentilerin doğru seçilip seçilmediğini de sorgular. Bölüm 28: Git içindeki kod incelemesinde yalnız değişen satırı değil, neyin korunmak istendiğini okuruz. Google'ın inceleme rehberi özellikle tasarımı, işlevi, karmaşıklığı ve testlerin gerçekten bozuk kodda başarısız olup olmayacağını sorgular. “Test dosyası eklendi” bir kabul ölçütü değildir; testin işe yaradığı gösterilmelidir.9
Örnek inceleme soruları: Bonus eşiği ürünün istediği eşik mi? Yetki kontrolü her kaynak için var mı? SQL hatasında işlem geri alınıyor mu? Testte beklenen sonuç, üretim fonksiyonunu tekrar çağırarak mı hesaplanmış? Sonuncusu sinsi bir hatadır: aynı yanlış hesabı hem gerçek sonuç hem beklenti olarak kullanırsan test bir değeri kendisiyle karşılaştırır. Beklentiyi küçük örneklerde bağımsız ve açık vermek gerekir.91
Sürekli entegrasyon (continuous integration, CI), değişiklikleri sık birleştirip ortak kodun derleme ve testlerini düzenli çalıştırma pratiğidir. Bir CI sistemi, yeni değişiklik geldiğinde otomatik denetimleri bir başka çalışma ortamında çalıştırabilir. GitHub Actions bunun araçlarından biridir; CI kavramının kendisi değildir. Bir değişikliğin yalnız yazarın bilgisayarında denenmiş kalmasını önlemeye yardım eder.10
Değişiklik önerisi → bağımlılıkları hazırla → derle ve statik denetle
→ dar testler → gerekli entegrasyon testleri → inceleme
Bu, çalıştırılmış bir GitHub iş akışı çıktısı değil, örnek denetim sırasıdır. İlk ok, değişikliğin ortak denetime girmesini gösterir. Bağımlılık hazırlığı kilit dosyalarını ve modül tanımlarını kullanır. Derleme ve Bölüm 29: Araçlar: Node, npm içindeki denetleyici bazı hataları çalıştırmadan bulur. Dar testler hızlı davranış geri bildirimi verir; entegrasyon testleri gerçek sınırları yoklar. Son adımda insan, yeşil denetimin hangi iddiaları kapsadığını ve nelerin eksik olduğunu okur.109
Yeşil CI, yalnız tanımlanmış denetimlerin o çalışmada geçtiği anlamına gelir. Üretim verisinin boyutunu, bütün kullanıcı cihazlarını veya saldırganın bütün yollarını kendiliğinden kapsamaz. Aynı şekilde otomatik test, kullanılabilirlik ve anlaşılabilirlik değerlendirmesini tamamen devralmaz. Yanlışta anlaşılmaz bir hata mesajı gören kullanıcı, sunucunun tüm testlerinin yeşil olmasından teselli bulmayacaktır.19
Önerilen küçük kabul paketi şu: hangi davranış değiştiğini bir cümleyle yaz; ilgili testi göster; hatayı yeniden üretiyorsa düzeltmeden önce nasıl kaldığını göster; son çalışmanın komutunu ve sonucunu ver; testin denemediği sınırı belirt. “Testler geçti” yerine “Go puan fonksiyonunun eşik altı/eşik/eşik üstü/yanlış cevap senaryoları geçti; gerçek veritabanı denenmedi” demek daha kullanışlı bir rapordur. Çalışma ağacı ve AGENTS.md ile bu disiplinin nasıl sürdürüleceği Bölüm 46: Agent'larla Geliştirme konusudur.910
Bir sonraki adım “testten geçti, artık herkese dağıtalım” demek değil; hangi ortamda, hangi yapılandırmayla, hangi geri dönüş yoluyla çalışacağını hazırlamaktır. Bölüm 43: Yayına Alma ve Bulut kalite denetimlerini yayın hattına bağlayacak. Burada CI'nin varlık nedenini kurduk; bir sonraki bölüm onu bir çalıştırma ortamı ve yayın sürecinin içine yerleştirecek.10
Bölüm 27: Modüler Kod puan hesabını ekranı güncellemekten ayırmıştı. Burada aynı ayrım sayesinde küçük fonksiyonu tarayıcı ve veritabanı olmadan sınadık. Modül yalnız klasör düzeni değildir; testin kurulumunu ve başarısızlığın yerini de küçültür. Gerçek Postgres sınırını ise onun yerine geçmeyen ayrı entegrasyon testlerine bıraktık.
Bu bölümde neler kuruldu
Birim testi dar davranışı, entegrasyon testi gerçek bağlantıyı, uçtan uca test kullanıcı yolculuğunu denetler. Test piramidi sabit oran değil kapsam ve maliyet sezgisidir. TDD başarısız beklenti, çalışan davranış ve yeniden düzenleme döngüsüdür. Go'da testing ve go test, JavaScript'te node:test ile küçük örnekler çalıştırdık. Test kapsamı doğruluk ispatı değildir; insan incelemesi beklentiyi sorgular, CI aynı denetimleri ortak değişiklik akışında çalıştırır.
Terimler sözlükte, Bölüm 42 başlığı altında.
Birincil okuma: Ham Vocke, The Practical Test Pyramid, özellikle The Test Pyramid, Unit tests, Integration Tests ve End-to-End Tests. Derinleşme: Go testing paketinin Overview ve Subtests and Sub-benchmarks kısımları; Fowler'ın Test Driven Development yazısı.
Takıldığın yeri yapay zekâ öğretmenine sor. Ondan puan kuralında bir sınır hatası oluşturmasını ve önce testin o hatayı yakalamasını iste. Sonra “bu test gerçek Postgres'i denedi mi?” diye sor; denemediyse hangi ayrı senaryonun gerektiğini sen tarif et.
Bölüm sonu soruları
Kitaba bakmadan cevapla. Önce gerekçeni düşün, sonra şıkkını seç.
Örnek cevabı göster
Saf puan fonksiyonu doğruyken veri yazma sınırı yanlış olabilir. Gerçek test Postgres'iyle eşzamanlı güncelleme, işlem ve tek ödül kısıtını denetleyen entegrasyon senaryosu gerekir. Yalnız sahte depo aynı yarış durumunu göstermeyebilir. Bkz. 42.1.
Örnek cevabı göster
Go puan fonksiyonunun dört alt testi ve JavaScript fonksiyonunun iki testi geçti; Go eşiği bilerek bozulunca tam eşik testi beklenen nedenle kaldı ve düzeltmeden sonra geçti. Bu denemeler gerçek Postgres, Redis, tarayıcı veya Expo uygulamasını çalıştırmadı. Böyle bir rapor hem kanıtı hem kapsam sınırını söyler. Bkz. 42.4.
Kaynaklar
- Ham Vocke, The Practical Test Pyramid, martinfowler.com: kapsam düzeyleri, dublörler, veri hazırlama, E2E ve kararsızlık.
- Go, testing paket belgesi: TestXxx, _test.go, T.Run ve T.Errorf.
- Martin Fowler, Test Driven Development: test listesi, red–green–refactor döngüsü ve arayüz tasarımı.
- Go, cmd/go: Test packages ve Testing flags; ./..., -count, -cover seçenekleri.
- Go, net/http/httptest: NewRequest ve ResponseRecorder; gerçek ağ açmadan işleyici deneme.
- Node.js, Test runner: node:test ve katı doğrulama ifadeleriyle test çalıştırma.
- Vitest, Getting Started: Vite tabanlı test çerçevesinin amacı.
- Playwright, Installation ve Introduction: web tarayıcısı tabanlı uçtan uca test kapsamı.
- Google Engineering Practices, What to look for in a code review: tasarım, işlev, test ve karmaşıklık.
- GitHub Docs, Continuous integration: ortak değişikliklerde otomatik derleme ve testler.