İçeriğe geç
Muhammet Şafak
en

Kararsız testler: %0,5'ten %98'e

800 testin her biri %0,5 ihtimalle boşuna patlıyorsa süit neredeyse her koşuda kırmızı. Retry neden tedavi değil, kararsızlığı ne yakalar?

%98

Süit büyüdükçe daha az güvenilir

Temiz bir çalıştırmada herhangi bir testin patlama ihtimali

%0,5 ihtimalle boşuna patlayan tek bir test görünmez. Aynısından 800 tane koy: 1 − 0,995^800 ≈ %98.

İhtimaller birikiyor

Test sayısı arttıkça yanlış kırmızı

en az bir testin boşuna patlaması, %

Test sayısı arttıkça yanlış kırmızı (en az bir testin boşuna patlaması, %): 100 test: 39,4, 200 test: 63,3, 300 test: 77,8, 400 test: 86,5, 500 test: 91,8, 600 test: 95,1, 700 test: 97, 800 test: 98,2, 900 test: 98,9, 1000 test: 99,3.

Formülden hesaplandı: 1 − 0,995^n. Ölçüm değil; yazıda yalnız n = 800 için ≈ %98 geçer.

Patlamalar bağımsız da değil

Yerelde 50 ms, yük altında timeout.

CI, paylaşımlı ve throttle'lı donanımda koşar; laptop'unda 50 ms'de biten async test, yük altında timeout'a düşer.

AI kararsızlığı icat etmedi, seri üretime geçirdi

Doğru görünen dört kalıp

  • Sabit bir sleepAsync işi "beklemek" için: time.Sleep(2 * time.Second), await page.waitForTimeout(2000), cy.wait(2000).
  • Seed'siz rastgelelikHer çalıştırmada farklı değer: Math.random(), rand.Intn(100), sabit seed'i olmayan bir faker.
  • Kırılgan bir selectorDOM yapısına çakılı: nth-child, otomatik üretilmiş bir class adı. Markup azıcık kayınca kırılır.
  • Her şeye bir mockTest bir sonucu değil bir etkileşimi doğrular.

Retry bir koşu bandı, tedavi değil

Hepsi reaktif

  • RetryGerçek CI dakikası yakar ve feedback loop'u uzatır; yeni hiçbir şey öğrenmemek için iki kez ödersin.
  • QuarantineSessizce büyüyen bir devre dışı test yığını. O yığın borçtur ve faiziyle büyür.
  • TicketBacklog gürültüsüne yaşlanır ve sessizce önemini yitirir.

Patlamayı değil, anti-pattern'i yakala

Ne zaman devreye giriyor?

Retry, quarantine, ticketCommit sınırında statik tarama
ZamanTest CI'ı zaten bozduktan sonraTest daha çalışmadan, diff'te
EtkiBelirtiyi gizler, bedelini sana keserBilinen anti-pattern'leri işaretler
TekrarlanabilirlikYeniden çalıştırınca geçer, sonra yine patlarAynı diff, aynı sonuç; model yok, network yok
KapsamTesti deterministik yapmazBariz kararsızlığı CI'a hiç ulaşmadan durdurur
Tan, defterine not alırken

Tespit emniyet ağı, asıl çözüm tasarım

Testi deterministik yaz

  • Sabit beklemeleri koşula dayalı beklemeyle değiştir. Saati değil, bir olguyu bekle. (bekliyor)
  • Her rastgele kaynağı seed'le; deterministik bir saat ve ID enjekte et. (bekliyor)
  • DOM pozisyonuna değil, role veya test id'ye göre seç. (bekliyor)
  • Logic'i değil, sınırı mock'la; en az bir gerçek integration yolunu koru. (bekliyor)

Bu kalıp ne zaman doğru cevap olmaktan çıkar?

Statik kapının sınırları

  • Akıllı race'i yakalamazBariz anti-pattern'leri yakalar, kendi kodunun içine gömülü bir race condition'ı değil.
  • Kuralları muhafazakâr tutGürültülü bir kapı yok sayılır; yok sayılan bir kapı ise hiç olmamasından kötüdür.
  • Sistem kararsızsaTest edilen sistem deterministik olmadığı için kararsız olan bir test, sana sistem hakkında bir şey söylüyor.

Yeniden çalıştırman gereken yeşil bir CI, yeşil değildir.

Kararsız bir testi öldürmenin en ucuz yeri, yazıldığı satır: sana bir build'e mal olmadan önce.

Tan, başparmağını kaldırmış onaylarken

Yazıldığı satırda

sade.dev

Kaynak: sade.dev, Kararsız Testler: Retry Çözüm Değil

Paylaş ve indir

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Escile kapatPagefind ile güçlendirildi