Yakın zamanda yapılan bir dağıtım, tüm birim testleri, entegrasyon testleri ve mock-sunucu kontrolleri geçmesine rağmen üç mikroservisi bozdu. Ekip, API mock'larını sözleşme testi (contract testing) ile değiştirdi. Altı ay içinde sözleşme sayısı üçten 47'ye yükseldi ve aylık entegrasyon hatası oranı iki vakadan sıfıra düştü.

Mock'lar sizi neden koruyamaz

Bir mock sunucu yalnızca tüketicinin beklediği yapıyı taklit eder; sağlayıcının (provider) gerçekten o yapıyı sunup sunmadığını asla kontrol etmez. Eğer bir sağlayıcı bir alanın adını değiştirirse —örneğin name yerine display_name yaparsa— mock hâlâ eski veri paketini (payload) döndürür, tüketicinin testleri yeşil kalmaya devam eder ve canlı sistem çöker. Bir Salı günü saat 14:00'teki üretim hatası tam olarak buydu: mock, gerçek sözleşme hakkında "yalan söyledi".

Sözleşme testi boşluğu doldurur

Sözleşme testi, herhangi bir kod üretim ortamına (production) çıkmadan önce bir API'nin iki tarafını ortak bir tanım üzerinde anlaşmaya zorlar. İki yaygın yaklaşım mevcuttur:

  • Consumer-driven contracts (Tüketici odaklı sözleşmeler) – tüketen servis beklentilerini yazar; sağlayan servis bunları doğrular. Bu, birlikte gelişen dahili mikroservisler için iyi çalışır.
  • Provider-driven contracts (Sağlayıcı odaklı sözleşmeler) – sağlayıcı bir spesifikasyon yayınlar; tüketiciler kodlarını buna göre kontrol eder. Bu, genel API'ler için alışılagelmiş bir modeldir.

İlk yaklaşım, genellikle bir mikroservis mimarisi içindeki bozuk entegrasyonları önler.

Tüketici odaklı bir sözleşme nasıl çalışır?

  1. Tüketici, sağlayıcıdan tam olarak neye ihtiyacı olduğunu açıklayan bir test yazar.
  2. Testi çalıştırmak bir pact dosyası oluşturur – bu, söz konusu beklentileri kaydeden bir JSON dokümanıdır.
  3. Sağlayıcı, CI hattında (pipeline) gerçek servisini pact dosyasına karşı çalıştırır.
  4. Eğer sağlayıcı bir alanı değiştirirse, doğrulama başarısız olur ve derleme (build) engellenir.

Doğrulama gerçek sağlayıcı kodu üzerinde çalıştığı için, herhangi bir bozucu değişiklik dağıtımdan sonra değil, erkenden yakalanır.

Sözleşme testleri test piramidinizin neresinde yer almalı?

  • Unit tests (Birim testleri) – hızlıdır, izole mantığı test eder.
  • Contract tests (Sözleşme testleri) – orta hızdadır, API anlaşmalarının geçerli olduğunu onaylar.
  • End-to-end tests (Uçtan uca testler) – yavaştır, tüm iş akışlarını çalıştırır.

Sözleşme testlerini, birim testlerinin hızlı geri bildirimi ile uçtan uca test setlerinin geniş kapsamı arasında bir köprü olarak değerlendirin. En sık bozulan entegrasyon noktalarını hedefleyin ve iki veya üç kritik uç nokta (endpoint) ile başlayın.

Gerçek dünyadan bir uygulama hikayesi

Bu makaleye ilham veren ekip, en kırılgan çağrılarını kapsayan üç sözleşme ile işe başladı. Altı ay sonra, servisler arası trafiğin büyük bir kısmını kapsayan 47 sözleşmeye sahiptiler. Bu süre zarfında API bozulma vakaları ayda ikiden sıfıra düştü.

Sözleşme testi ne zaman zahmetine değmeyebilir?

  • Tüm servisleri tek bir depoda (repository) tutan bir solo geliştiriciyseniz.
  • API olağanüstü derecede kararlıysa ve yıllardır değişmediyse.
  • Yakında atılacak geçici bir prototip oluşturuyorsanız.

Bu senaryolarda, sözleşmeleri sürdürmenin getirdiği yük, sağladığı faydadan daha fazla olabilir.

Potansiyel dezavantajlar ve bunları nasıl azaltabilirsiniz?

  • Sözleşmeleri, tanımladıkları kodla birlikte versiyonlayın.
  • Eski (stale) sözleşmelerden kaçınmak için her CI çalışmasında doğrulamayı otomatize edin.
  • Kazara oluşan bozulmaları yakalamak için sözleşme değişikliklerini pull request'lerde inceleyin.

Özet

Eğer servislerinizin birbiriyle iletişim kurabildiğine kendinizi ikna etmek için hâlâ elle hazırlanmış mock'lara güveniyorsanız, sahte bir vaat üzerine bahis oynuyorsunuz demektir. Sözleşme testi bu bahsi doğrulanabilir bir anlaşmaya dönüştürür; bozucu değişiklikleri üretim ortamına ulaşmadan yakalar ve ekibin rakamlarının da gösterdiği gibi, entegrasyon hatalarını tamamen ortadan kaldırabilir.