{"id":44445,"date":"2026-08-31T21:12:49","date_gmt":"2026-08-31T18:12:49","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/"},"modified":"2026-08-31T21:13:21","modified_gmt":"2026-08-31T18:13:21","slug":"google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/","title":{"rendered":"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi"},"content":{"rendered":"<h2>Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi<\/h2>\n<p>Google ADK (Agent Development Kit) ile geli\u015ftirilen TypeScript tabanl\u0131 ajanlar, modern uygulamalar\u0131n ve etkile\u015fimli sistemlerin kalbinde yer al\u0131yor. Ancak bu ak\u0131ll\u0131 ajanlar\u0131 test etmek, \u00f6zellikle de karma\u015f\u0131k diyalog ak\u0131\u015flar\u0131 ve d\u0131\u015f servis entegrasyonlar\u0131 s\u00f6z konusu oldu\u011funda, \u00e7o\u011fu zaman &#8220;c\u00fcmleleri kovalamak&#8221; gibi zorlay\u0131c\u0131 bir s\u00fcrece d\u00f6n\u00fc\u015febilir. Bu makale, TypeScript ajanlar\u0131n\u0131z\u0131 daha verimli, g\u00fcvenilir ve mod\u00fcler bir \u015fekilde test etmeniz i\u00e7in kapsaml\u0131 bir rehber sunarak, geli\u015ftirme s\u00fcrecinizi h\u0131zland\u0131rmay\u0131 ve kod kalitenizi art\u0131rmay\u0131 hedefliyor.<\/p>\n<p>Google ADK TypeScript ajanlar\u0131, kullan\u0131c\u0131larla etkile\u015fim kuran, belirli g\u00f6revleri otomatikle\u015ftiren veya karma\u015f\u0131k i\u015f mant\u0131\u011f\u0131n\u0131 y\u00fcr\u00fcten yaz\u0131l\u0131m bile\u015fenleridir. Bu ajanlar genellikle diyalog sistemleri (\u00f6rne\u011fin, chatbotlar, sesli asistanlar), otomasyon betikleri veya arka plan servisleri olarak i\u015flev g\u00f6r\u00fcrler. TypeScript&#8217;in sa\u011flad\u0131\u011f\u0131 tip g\u00fcvenli\u011fi ve modern dil \u00f6zellikleri, bu t\u00fcr ajanlar\u0131n geli\u015ftirilmesini kolayla\u015ft\u0131rsa da, test s\u00fcre\u00e7leri \u00e7o\u011fu zaman g\u00f6z ard\u0131 edilir veya yetersiz kal\u0131r. Geleneksel test yakla\u015f\u0131mlar\u0131, ajanlar\u0131n karma\u015f\u0131k etkile\u015fimlerini ve d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131 sim\u00fcle etmede yetersiz kalabilir, bu da hatalar\u0131n \u00fcretim ortam\u0131na s\u0131zmas\u0131na yol a\u00e7abilir. Bu durum, geli\u015ftiricilerin saatlerce s\u00fcren manuel testler yapmas\u0131na veya hatalar\u0131 ay\u0131klamak i\u00e7in uzun diyalog ak\u0131\u015flar\u0131n\u0131 tekrar tekrar takip etmesine neden olur; bu da makalenin ba\u015fl\u0131\u011f\u0131ndaki &#8220;c\u00fcmleleri kovalamak&#8221; metaforunu ortaya \u00e7\u0131kar\u0131r. Amac\u0131m\u0131z, bu zorluklar\u0131 a\u015fmak ve geli\u015ftiricilere, ajanlar\u0131n\u0131n temel i\u015f mant\u0131\u011f\u0131n\u0131, d\u0131\u015f entegrasyonlar\u0131n\u0131 ve u\u00e7tan uca davran\u0131\u015flar\u0131n\u0131 sistematik bir \u015fekilde test etmeleri i\u00e7in pratik stratejiler ve ara\u00e7lar sunmakt\u0131r. Bu sayede, ajanlar\u0131n\u0131z\u0131n beklenen \u015fekilde \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olabilir, geli\u015ftirme d\u00f6ng\u00fcs\u00fcn\u00fc k\u0131saltabilir ve daha g\u00fcvenilir uygulamalar sunabilirsiniz.<\/p>\n<h2>Google ADK ve TypeScript Ajanlar\u0131 Neden \u00d6nemli? Temel Kavramlara Derin Bir Bak\u0131\u015f<\/h2>\n<p>Google ADK (Agent Development Kit) kavram\u0131, genellikle Google Cloud ekosisteminde, \u00f6zellikle yapay zeka ve makine \u00f6\u011frenimi servisleriyle etkile\u015fim kuran ak\u0131ll\u0131 ajanlar\u0131n geli\u015ftirilmesi i\u00e7in kullan\u0131lan bir dizi ara\u00e7, k\u00fct\u00fcphane ve \u00e7er\u00e7eveyi (framework) ifade eder. Bu ajanlar, Dialogflow gibi diyalogsal yapay zeka platformlar\u0131ndan, Google Cloud Functions veya Cloud Run \u00fczerinde \u00e7al\u0131\u015fan sunucusuz (serverless) arka u\u00e7lara kadar geni\u015f bir yelpazede konumlanabilir. Temel ama\u00e7, kullan\u0131c\u0131 giri\u015flerini i\u015flemek, belirli kararlar almak ve ilgili yan\u0131tlar\u0131 veya eylemleri tetiklemektir. \u00d6rne\u011fin, bir m\u00fc\u015fteri hizmetleri chatbotu, bir sipari\u015f takip sistemi veya bir otomasyon arac\u0131 bir Google ADK TypeScript ajan\u0131 olarak d\u00fc\u015f\u00fcn\u00fclebilir.<\/p>\n<p>Peki, bu ajanlar\u0131n geli\u015ftirilmesinde neden \u00f6zellikle TypeScript tercih ediliyor? JavaScript&#8217;in tip g\u00fcvenli\u011fi olmayan do\u011fas\u0131, \u00f6zellikle b\u00fcy\u00fck ve karma\u015f\u0131k projelerde, hatalara ve bak\u0131m zorluklar\u0131na yol a\u00e7abilir. TypeScript, JavaScript&#8217;in \u00fczerine in\u015fa edilmi\u015f, iste\u011fe ba\u011fl\u0131 statik tip denetimi sunan bir \u00fcst k\u00fcmedir. Bu, geli\u015ftiricilerin kodlar\u0131na tip bilgisi eklemesine olanak tan\u0131r, bu da derleme zaman\u0131nda potansiyel hatalar\u0131n yakalanmas\u0131n\u0131 sa\u011flar. Bu \u00f6zellik, \u00f6zellikle \u015fu a\u00e7\u0131lardan kritik \u00f6neme sahiptir:<\/p>\n<ul>\n<li><strong>Kod Kalitesi ve Bak\u0131m Kolayl\u0131\u011f\u0131:<\/strong> Tip tan\u0131mlar\u0131 sayesinde, kod daha okunabilir ve anla\u015f\u0131l\u0131r hale gelir. Bir fonksiyonun hangi t\u00fcrde arg\u00fcmanlar bekledi\u011fi ve hangi t\u00fcrde de\u011fer d\u00f6nd\u00fcrd\u00fc\u011f\u00fc a\u00e7\u0131k\u00e7a belirtildi\u011fi i\u00e7in, farkl\u0131 geli\u015ftiricilerin ayn\u0131 kod taban\u0131nda \u00e7al\u0131\u015fmas\u0131 kolayla\u015f\u0131r. Bu, uzun vadede kodun s\u00fcrd\u00fcr\u00fclebilirli\u011fini ve bak\u0131m\u0131n\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde iyile\u015ftirir.<\/li>\n<li><strong>Hata Yakalama:<\/strong> Derleme zaman\u0131nda tip hatalar\u0131n\u0131 yakalamak, \u00e7al\u0131\u015fma zaman\u0131 (runtime) hatalar\u0131n\u0131n \u00f6n\u00fcne ge\u00e7er. Bu, \u00f6zellikle d\u0131\u015f servislerle entegrasyonlarda veya karma\u015f\u0131k veri yap\u0131lar\u0131 \u00fczerinde \u00e7al\u0131\u015f\u0131rken kritik bir avantajd\u0131r. \u00d6rne\u011fin, bir API&#8217;den beklenen veri yap\u0131s\u0131 de\u011fi\u015fti\u011finde, TypeScript bu de\u011fi\u015fikli\u011fi derleme a\u015famas\u0131nda fark etmenizi sa\u011flar.<\/li>\n<li><strong>Geli\u015ftirici Deneyimi:<\/strong> Modern IDE&#8217;ler (Entegre Geli\u015ftirme Ortam\u0131), TypeScript&#8217;in tip bilgilerini kullanarak ak\u0131ll\u0131 otomatik tamamlama (autocompletion), yeniden d\u00fczenleme (refactoring) ve hata kontrol\u00fc gibi \u00f6zellikler sunar. Bu, geli\u015ftirme s\u00fcrecini h\u0131zland\u0131r\u0131r ve geli\u015ftiricilerin daha verimli \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flar.<\/li>\n<li><strong>\u00d6l\u00e7eklenebilirlik:<\/strong> B\u00fcy\u00fck ve b\u00fcy\u00fcyen ajan projelerinde, tip g\u00fcvenli\u011fi kodun tutarl\u0131l\u0131\u011f\u0131n\u0131 korumaya yard\u0131mc\u0131 olur. Yeni \u00f6zellikler eklendik\u00e7e veya mevcut kod refakt\u00f6r edildi\u011finde, tip sistemi olas\u0131 yan etkileri veya uyumsuzluklar\u0131 tespit etmeye yard\u0131mc\u0131 olur, bu da projenin daha \u00f6l\u00e7eklenebilir olmas\u0131n\u0131 sa\u011flar.<\/li>\n<\/ul>\n<p>Ancak, TypeScript&#8217;in sa\u011flad\u0131\u011f\u0131 avantajlara ra\u011fmen, Google ADK TypeScript ajanlar\u0131n\u0131 test etmek kendi i\u00e7inde zorluklar bar\u0131nd\u0131r\u0131r. Bu zorluklar genellikle ajan\u0131n do\u011fas\u0131ndan kaynaklan\u0131r:<\/p>\n<ul>\n<li><strong>D\u0131\u015f Ba\u011f\u0131ml\u0131l\u0131klar:<\/strong> Ajanlar genellikle Google Cloud API&#8217;leri (\u00f6rne\u011fin, Firestore, Cloud Storage), \u00fc\u00e7\u00fcnc\u00fc taraf API&#8217;ler veya veritabanlar\u0131 gibi d\u0131\u015f servislerle etkile\u015fim kurar. Bu ba\u011f\u0131ml\u0131l\u0131klar, test ortam\u0131nda ger\u00e7ek servisleri kullanmadan izole testler yazmay\u0131 zorla\u015ft\u0131r\u0131r.<\/li>\n<li><strong>Asenkron \u0130\u015flemler:<\/strong> \u00c7o\u011fu ajan\u0131n i\u015f mant\u0131\u011f\u0131 asenkron (asynchronous) i\u015flemler i\u00e7erir (API \u00e7a\u011fr\u0131lar\u0131, veritaban\u0131 sorgular\u0131). Bu asenkron yap\u0131y\u0131 do\u011fru bir \u015fekilde test etmek, test \u00e7er\u00e7evelerinin (testing frameworks) ve yakla\u015f\u0131mlar\u0131n\u0131n dikkatli kullan\u0131m\u0131n\u0131 gerektirir.<\/li>\n<li><strong>Diyaloga Dayal\u0131 Mant\u0131k:<\/strong> \u00d6zellikle chatbot veya sesli asistan ajanlar\u0131 i\u00e7in, i\u015f mant\u0131\u011f\u0131 genellikle bir diyalog ak\u0131\u015f\u0131na g\u00f6m\u00fcl\u00fcd\u00fcr. Kullan\u0131c\u0131n\u0131n farkl\u0131 girdilerine veya ba\u011flam\u0131na g\u00f6re ajan\u0131n nas\u0131l tepki verdi\u011fini test etmek, &#8220;c\u00fcmleleri kovalamak&#8221; anlam\u0131na gelen karma\u015f\u0131k senaryolar\u0131n sim\u00fclasyonunu gerektirebilir.<\/li>\n<li><strong>Durum Y\u00f6netimi (State Management):<\/strong> Ajanlar, kullan\u0131c\u0131 oturumlar\u0131 veya belirli bir g\u00f6revdeki ilerleme gibi durumlar\u0131 y\u00f6netebilir. Bu durumun farkl\u0131 a\u015famalar\u0131nda ajan\u0131n davran\u0131\u015f\u0131n\u0131 test etmek, test senaryolar\u0131n\u0131 daha karma\u015f\u0131k hale getirir.<\/li>\n<li><strong>Performans ve G\u00fcvenilirlik:<\/strong> \u00dcretim ortam\u0131nda ajan\u0131n h\u0131zl\u0131 ve hatas\u0131z \u00e7al\u0131\u015fmas\u0131 beklenir. Bu nedenle, sadece fonksiyonel do\u011frulu\u011fu de\u011fil, ayn\u0131 zamanda performans ve hata tolerans\u0131n\u0131 da test etmek \u00f6nemlidir.<\/li>\n<\/ul>\n<p>Bu zorluklar\u0131n \u00fcstesinden gelmek, do\u011fru test stratejileri ve ara\u00e7lar\u0131n\u0131 benimsemeyi gerektirir. Bir sonraki b\u00f6l\u00fcmde, ajanlar\u0131n\u0131z\u0131 daha mod\u00fcler ve test edilebilir hale getirecek stratejilere odaklanaca\u011f\u0131z.<\/p>\n<h2>Test Stratejileri: Bir Ajan\u0131 Mod\u00fcler \u015eekilde Nas\u0131l Test Edebiliriz?<\/h2>\n<p>Google ADK TypeScript ajanlar\u0131n\u0131 test etmek, geleneksel yaz\u0131l\u0131m test prensiplerini ajan\u0131n \u00f6zel do\u011fas\u0131na uyarlamay\u0131 gerektirir. &#8220;C\u00fcmleleri kovalamadan&#8221; etkin bir test s\u00fcreci olu\u015fturman\u0131n anahtar\u0131, ajan\u0131n i\u015f mant\u0131\u011f\u0131n\u0131, d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131 ve diyalog ak\u0131\u015flar\u0131n\u0131 m\u00fcmk\u00fcn oldu\u011funca birbirinden ay\u0131rarak mod\u00fcler bir yap\u0131 kurmakt\u0131r. Bu, testlerin daha h\u0131zl\u0131, daha g\u00fcvenilir ve daha kolay yaz\u0131labilir olmas\u0131n\u0131 sa\u011flar. Temel olarak \u00fc\u00e7 ana test seviyesi \u00fczerinde durulur: birim testleri (unit tests), entegrasyon testleri (integration tests) ve u\u00e7tan uca testler (end-to-end tests).<\/p>\n<h3>Birim Testleri (Unit Tests): Saf Fonksiyonlar\u0131 ve \u0130\u015f Mant\u0131\u011f\u0131n\u0131 \u0130zole Etme<\/h3>\n<p>Birim testleri, uygulaman\u0131z\u0131n en k\u00fc\u00e7\u00fck, ba\u011f\u0131ms\u0131z ve test edilebilir birimlerini (genellikle fonksiyonlar veya metotlar) test etmeye odaklan\u0131r. Bir ADK TypeScript ajan\u0131 ba\u011flam\u0131nda, bu, diyalog ak\u0131\u015f\u0131ndan veya d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klardan tamamen izole edilmi\u015f saf i\u015f mant\u0131\u011f\u0131 fonksiyonlar\u0131n\u0131 test etmek anlam\u0131na gelir. \u00d6rne\u011fin, bir sipari\u015f takip ajan\u0131n\u0131n sipari\u015f numaras\u0131n\u0131 do\u011frulayan bir fonksiyonu veya bir \u00fcr\u00fcn fiyat\u0131n\u0131 hesaplayan bir fonksiyonu birim testi ile test edilebilir.<\/p>\n<p>Birim testlerinin temel avantajlar\u0131 \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>H\u0131z:<\/strong> D\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131 olmad\u0131\u011f\u0131 i\u00e7in \u00e7ok h\u0131zl\u0131 \u00e7al\u0131\u015f\u0131rlar.<\/li>\n<li><strong>\u0130zolasyon:<\/strong> Her birim ba\u011f\u0131ms\u0131z olarak test edildi\u011fi i\u00e7in, bir testin ba\u015far\u0131s\u0131z olmas\u0131 do\u011frudan o birimdeki bir hatay\u0131 i\u015faret eder.<\/li>\n<li><strong>Hata Yeri Tespiti:<\/strong> Hatan\u0131n nerede oldu\u011funu bulmak \u00e7ok daha kolayd\u0131r.<\/li>\n<li><strong>Refakt\u00f6r G\u00fcvenli\u011fi:<\/strong> Kodu refakt\u00f6r ederken, mevcut birim testleri yeni de\u011fi\u015fikliklerin mevcut i\u015flevselli\u011fi bozup bozmad\u0131\u011f\u0131n\u0131 kontrol etmeye yard\u0131mc\u0131 olur.<\/li>\n<\/ul>\n<p>Bir ajan geli\u015ftirirken, i\u015f mant\u0131\u011f\u0131n\u0131 m\u00fcmk\u00fcn oldu\u011funca diyalog ak\u0131\u015f\u0131ndan ve platforma \u00f6zg\u00fc koddan ay\u0131rmaya \u00e7al\u0131\u015fmal\u0131s\u0131n\u0131z. \u00d6rne\u011fin, bir kullan\u0131c\u0131n\u0131n iste\u011fini i\u015fleyecek bir fonksiyon, bu iste\u011fi Dialogflow&#8217;dan m\u0131 yoksa ba\u015fka bir kaynaktan m\u0131 geldi\u011finden ba\u011f\u0131ms\u0131z olarak \u00e7al\u0131\u015fmal\u0131d\u0131r. Bu &#8220;saf fonksiyonlar&#8221; yakla\u015f\u0131m\u0131, test edilebilirli\u011fi art\u0131r\u0131r.<\/p>\n<h3>Entegrasyon Testleri (Integration Tests): Ba\u011f\u0131ml\u0131l\u0131klarla Etkile\u015fimi Do\u011frulama<\/h3>\n<p>Entegrasyon testleri, farkl\u0131 birimlerin veya mod\u00fcllerin birbiriyle ve d\u0131\u015f sistemlerle (veritabanlar\u0131, API&#8217;ler, di\u011fer servisler) nas\u0131l etkile\u015fim kurdu\u011funu test eder. Bir ADK TypeScript ajan\u0131 i\u00e7in bu, ajan\u0131n Google Cloud API&#8217;leri (Firestore, Cloud Storage gibi), \u00fc\u00e7\u00fcnc\u00fc taraf API&#8217;ler veya \u00f6zel arka u\u00e7 servisleriyle do\u011fru \u015fekilde ileti\u015fim kurup kurmad\u0131\u011f\u0131n\u0131 kontrol etmek anlam\u0131na gelir. Entegrasyon testlerinde, d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131n ger\u00e7ek versiyonlar\u0131n\u0131 kullanmak yerine, genellikle &#8220;mock&#8221; (sahte) veya &#8220;stub&#8221; (taklit) nesneler kullan\u0131l\u0131r. Bu sayede testler daha h\u0131zl\u0131 ve izole bir \u015fekilde \u00e7al\u0131\u015f\u0131r.<\/p>\n<p>Entegrasyon testlerinin avantajlar\u0131:<\/p>\n<ul>\n<li><strong>Mod\u00fcl Etkile\u015fimlerini Do\u011frulama:<\/strong> Farkl\u0131 bile\u015fenlerin bir araya geldi\u011finde do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olur.<\/li>\n<li><strong>D\u0131\u015f Servis Etkile\u015fimlerini Sim\u00fcle Etme:<\/strong> Ger\u00e7ek servisleri kullanmadan d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klarla olan ileti\u015fimi test etme olana\u011f\u0131 sunar.<\/li>\n<li><strong>Daha Kapsaml\u0131 Hata Yakalama:<\/strong> Birim testlerinin yakalayamad\u0131\u011f\u0131, farkl\u0131 mod\u00fcller aras\u0131ndaki etkile\u015fimden kaynaklanan hatalar\u0131 tespit eder.<\/li>\n<\/ul>\n<p>\u00d6rne\u011fin, bir ajan\u0131n bir kullan\u0131c\u0131n\u0131n sipari\u015f bilgilerini Firestore&#8217;dan \u00e7ekmesi gerekiyorsa, entegrasyon testi, Firestore istemcisinin do\u011fru parametrelerle \u00e7a\u011fr\u0131ld\u0131\u011f\u0131n\u0131 ve beklenen veriyi d\u00f6nd\u00fcrd\u00fc\u011f\u00fcn\u00fc (mocklanm\u0131\u015f bir cevapla) do\u011frular. Bu, Firestore&#8217;un kendisinin do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 test etmek yerine, ajan\u0131n Firestore ile olan aray\u00fcz\u00fcn\u00fcn do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 test eder.<\/p>\n<h3>U\u00e7tan Uca Testler (End-to-End Tests &#8211; E2E): Ger\u00e7ek Kullan\u0131c\u0131 Deneyimini Sim\u00fcle Etme<\/h3>\n<p>U\u00e7tan uca testler, bir uygulaman\u0131n t\u00fcm ak\u0131\u015f\u0131n\u0131, kullan\u0131c\u0131n\u0131n bak\u0131\u015f a\u00e7\u0131s\u0131ndan test eder. Bir ADK TypeScript ajan\u0131 i\u00e7in bu, bir kullan\u0131c\u0131n\u0131n ajana bir istek g\u00f6ndermesinden (\u00f6rne\u011fin, bir mesaj veya sesli komut) ajan\u0131n nihai yan\u0131t\u0131 veya eylemi ger\u00e7ekle\u015ftirmesine kadar olan t\u00fcm s\u00fcreci sim\u00fcle etmek anlam\u0131na gelir. Bu testler, genellikle ajan\u0131n da\u011f\u0131t\u0131ld\u0131\u011f\u0131 platformda (Dialogflow konsolu, \u00f6zel bir web aray\u00fcz\u00fc vb.) ger\u00e7ek veya sanal bir kullan\u0131c\u0131 etkile\u015fimini taklit eder.<\/p>\n<p>E2E testlerinin faydalar\u0131:<\/p>\n<ul>\n<li><strong>Ger\u00e7ek D\u00fcnya Senaryolar\u0131:<\/strong> Uygulaman\u0131n \u00fcretim ortam\u0131nda nas\u0131l davranaca\u011f\u0131n\u0131 en do\u011fru \u015fekilde yans\u0131t\u0131r.<\/li>\n<li><strong>Sistem Entegrasyonunu Do\u011frulama:<\/strong> T\u00fcm sistemin (\u00f6n u\u00e7, arka u\u00e7, veritabanlar\u0131, d\u0131\u015f servisler) bir b\u00fct\u00fcn olarak \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olur.<\/li>\n<li><strong>Kullan\u0131c\u0131 Deneyimini Onaylama:<\/strong> Kullan\u0131c\u0131n\u0131n bekledi\u011fi ak\u0131\u015f\u0131n ve yan\u0131tlar\u0131n do\u011fru oldu\u011funu do\u011frular.<\/li>\n<\/ul>\n<p>Ancak E2E testleri genellikle yava\u015ft\u0131r, bak\u0131m\u0131 zordur ve bir hata durumunda hatan\u0131n tam yerini tespit etmek daha karma\u015f\u0131kt\u0131r. Bu nedenle, genellikle birim ve entegrasyon testleriyle birlikte, kritik kullan\u0131c\u0131 ak\u0131\u015flar\u0131n\u0131 kapsayacak \u015fekilde s\u0131n\u0131rl\u0131 say\u0131da kullan\u0131l\u0131rlar. \u00d6rne\u011fin, bir kullan\u0131c\u0131n\u0131n &#8220;Sipari\u015fimi takip et&#8221; demesiyle ba\u015flayan, sipari\u015f numaras\u0131n\u0131 girmesiyle devam eden ve ajan\u0131n sipari\u015f durumunu bildirmesiyle biten bir senaryo E2E testi ile kapsanabilir.<\/p>\n<h3>Test Piramidi Yakla\u015f\u0131m\u0131<\/h3>\n<p>Etkin bir test stratejisi i\u00e7in genellikle &#8220;Test Piramidi&#8221; yakla\u015f\u0131m\u0131 \u00f6nerilir:<\/p>\n<ul>\n<li><strong>Taban (Geni\u015f): Birim Testleri:<\/strong> En \u00e7ok say\u0131da ve en h\u0131zl\u0131 testlerdir. \u0130\u015f mant\u0131\u011f\u0131n\u0131n \u00e7o\u011funu kapsar.<\/li>\n<li><strong>Orta K\u0131s\u0131m: Entegrasyon Testleri:<\/strong> Orta say\u0131da ve orta h\u0131zda testlerdir. Mod\u00fcl etkile\u015fimlerini ve d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131 mocklayarak test eder.<\/li>\n<li><strong>Tepe (Dar): U\u00e7tan Uca Testler:<\/strong> En az say\u0131da ve en yava\u015f testlerdir. Kritik kullan\u0131c\u0131 ak\u0131\u015flar\u0131n\u0131 kapsar.<\/li>\n<\/ul>\n<p>Bu piramit, testlerin maliyetini ve h\u0131z\u0131n\u0131 dengeleyerek en iyi kapsay\u0131c\u0131l\u0131\u011f\u0131 sa\u011flar. Bir sonraki b\u00f6l\u00fcmde, bu stratejileri uygulamak i\u00e7in TypeScript ile bir test ortam\u0131n\u0131n nas\u0131l kurulaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m inceleyece\u011fiz.<\/p>\n<h2>TypeScript ile Test Ortam\u0131 Kurulumu: Ad\u0131m Ad\u0131m Rehber<\/h2>\n<p>Google ADK TypeScript ajanlar\u0131n\u0131z\u0131 verimli bir \u015fekilde test etmek i\u00e7in sa\u011flam bir test ortam\u0131 kurmak kritik \u00f6neme sahiptir. Bu b\u00f6l\u00fcm, pop\u00fcler bir test \u00e7er\u00e7evesi olan Jest&#8217;i kullanarak TypeScript projeleriniz i\u00e7in ad\u0131m ad\u0131m bir test ortam\u0131 kurulumunu ve temel birim testi \u00f6rne\u011fini i\u00e7erecektir. Jest, s\u0131f\u0131r yap\u0131land\u0131rma (zero-config) felsefesi, h\u0131zl\u0131 \u00e7al\u0131\u015fma s\u00fcresi ve g\u00fc\u00e7l\u00fc mocking yetenekleri sayesinde TypeScript projeleri i\u00e7in ideal bir se\u00e7imdir.<\/p>\n<h3>1. Proje Yap\u0131s\u0131 ve Ba\u011f\u0131ml\u0131l\u0131klar\u0131n Kurulumu<\/h3>\n<p>\u00d6ncelikle, yeni bir TypeScript projesi ba\u015flatal\u0131m veya mevcut projemizin k\u00f6k dizininde oldu\u011fumuzdan emin olal\u0131m. Gerekli ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fcklemek i\u00e7in terminali kullan\u0131n:<\/p>\n<div class=\"code-container\">\n<pre><code>\nnpm init -y\nnpm install typescript ts-node @types\/node --save-dev\nnpm install jest @types\/jest ts-jest --save-dev\n  <\/code><\/pre>\n<\/div>\n<ul>\n<li><code>typescript<\/code>: TypeScript derleyicisi.<\/li>\n<li><code>ts-node<\/code>: TypeScript dosyalar\u0131n\u0131 do\u011frudan \u00e7al\u0131\u015ft\u0131rmak i\u00e7in (testler i\u00e7in genellikle dolayl\u0131 kullan\u0131l\u0131r).<\/li>\n<li><code>@types\/node<\/code>: Node.js i\u00e7in tip tan\u0131mlar\u0131.<\/li>\n<li><code>jest<\/code>: Test \u00e7er\u00e7evemiz.<\/li>\n<li><code>@types\/jest<\/code>: Jest i\u00e7in tip tan\u0131mlar\u0131.<\/li>\n<li><code>ts-jest<\/code>: Jest&#8217;in TypeScript dosyalar\u0131n\u0131 anlamas\u0131n\u0131 sa\u011flayan bir \u00f6ni\u015flemci (preprocessor).<\/li>\n<\/ul>\n<h3>2. TypeScript Yap\u0131land\u0131rmas\u0131 (tsconfig.json)<\/h3>\n<p>TypeScript derleyicisinin nas\u0131l davranaca\u011f\u0131n\u0131 belirtmek i\u00e7in bir <code>tsconfig.json<\/code> dosyas\u0131 olu\u015fturun:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ tsconfig.json\n{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"commonjs\",\n    \"rootDir\": \".\/src\",\n    \"outDir\": \".\/dist\",\n    \"esModuleInterop\": true,\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true\n  },\n  \"include\": [\"src\/**\/*.ts\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n  <\/code><\/pre>\n<\/div>\n<p>Bu yap\u0131land\u0131rma, modern JavaScript \u00f6zelliklerini kullanmam\u0131z\u0131 ve dosyalar\u0131m\u0131z\u0131n <code>src<\/code> dizininde oldu\u011funu varsayar. Test dosyalar\u0131 i\u00e7in ayr\u0131 bir <code>tsconfig.json<\/code> olu\u015fturmak da m\u00fcmk\u00fcnd\u00fcr, ancak \u00e7o\u011fu k\u00fc\u00e7\u00fck ve orta \u00f6l\u00e7ekli proje i\u00e7in bu yeterlidir.<\/p>\n<h3>3. Jest Yap\u0131land\u0131rmas\u0131 (jest.config.js)<\/h3>\n<p>Jest&#8217;in TypeScript ile nas\u0131l \u00e7al\u0131\u015faca\u011f\u0131n\u0131 belirtmek i\u00e7in proje k\u00f6k dizinine <code>jest.config.js<\/code> ad\u0131nda bir dosya ekleyin:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ jest.config.js\nmodule.exports = {\n  preset: 'ts-jest',\n  testEnvironment: 'node',\n  testMatch: [\"**\/?(*.)+(spec|test).[jt]s?(x)\"],\n  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],\n  collectCoverage: true, \/\/ Kod kapsay\u0131c\u0131l\u0131\u011f\u0131 raporlamas\u0131n\u0131 etkinle\u015ftirir\n  coverageDirectory: \"coverage\",\n  coveragePathIgnorePatterns: [\n    \"\/node_modules\/\",\n    \"\/dist\/\"\n  ]\n};\n  <\/code><\/pre>\n<\/div>\n<ul>\n<li><code>preset: 'ts-jest'<\/code>: Jest&#8217;e TypeScript dosyalar\u0131n\u0131 <code>ts-jest<\/code> ile i\u015flemesini s\u00f6yler.<\/li>\n<li><code>testEnvironment: 'node'<\/code>: Testlerin Node.js ortam\u0131nda \u00e7al\u0131\u015faca\u011f\u0131n\u0131 belirtir (taray\u0131c\u0131 ortam\u0131 yerine).<\/li>\n<li><code>testMatch<\/code>: Jest&#8217;in hangi dosyalar\u0131 test olarak kabul edece\u011fini tan\u0131mlar (genellikle <code>.test.ts<\/code> veya <code>.spec.ts<\/code> uzant\u0131l\u0131 dosyalar).<\/li>\n<li><code>collectCoverage: true<\/code>: Testlerin kod kapsam\u0131n\u0131 \u00f6l\u00e7mesini sa\u011flar.<\/li>\n<\/ul>\n<h3>4. Temel Ajan Fonksiyonu ve Birim Testi \u00d6rne\u011fi<\/h3>\n<p>\u015eimdi bir \u00f6rnek ajan fonksiyonu ve buna ait bir birim testi yazal\u0131m. Diyelim ki ajan\u0131z\u0131n bir par\u00e7as\u0131 olarak basit bir selamla\u015fma mesaj\u0131 \u00fcreten bir fonksiyonunuz var.<\/p>\n<p><code>src\/agentLogic.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/agentLogic.ts\nexport function generateGreeting(name?: string): string {\n  if (name) {\n    return <code>Merhaba, ${name}! Size nas\u0131l yard\u0131mc\u0131 olabilirim?<\/code>;\n  }\n  return \"Merhaba! Size nas\u0131l yard\u0131mc\u0131 olabilirim?\";\n}\n\nexport function calculateOrderTotal(items: { price: number; quantity: number }[]): number {\n  if (!items || items.length === 0) {\n    return 0;\n  }\n  return items.reduce((total, item) => total + (item.price * item.quantity), 0);\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/agentLogic.test.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/agentLogic.test.ts\nimport { generateGreeting, calculateOrderTotal } from '.\/agentLogic';\n\ndescribe('generateGreeting', () => {\n  test('isim belirtilmedi\u011finde genel bir selamla\u015fma d\u00f6nmeli', () => {\n    expect(generateGreeting()).toBe('Merhaba! Size nas\u0131l yard\u0131mc\u0131 olabilirim?');\n  });\n\n  test('isim belirtildi\u011finde ki\u015fiselle\u015ftirilmi\u015f bir selamla\u015fma d\u00f6nmeli', () => {\n    expect(generateGreeting('Ali')).toBe('Merhaba, Ali! Size nas\u0131l yard\u0131mc\u0131 olabilirim?');\n  });\n\n  test('bo\u015f string isimde genel selamla\u015fma d\u00f6nmeli', () => {\n    expect(generateGreeting('')).toBe('Merhaba, ! Size nas\u0131l yard\u0131mc\u0131 olabilirim?'); \/\/ Kas\u0131tl\u0131 olarak bo\u015f string ile test ediyoruz\n  });\n});\n\ndescribe('calculateOrderTotal', () => {\n  test('bo\u015f \u00fcr\u00fcn listesi i\u00e7in 0 d\u00f6nmeli', () => {\n    expect(calculateOrderTotal([])).toBe(0);\n  });\n\n  test('tek \u00fcr\u00fcn i\u00e7in do\u011fru toplam\u0131 hesaplamal\u0131', () => {\n    const items = [{ price: 100, quantity: 1 }];\n    expect(calculateOrderTotal(items)).toBe(100);\n  });\n\n  test('birden fazla \u00fcr\u00fcn i\u00e7in do\u011fru toplam\u0131 hesaplamal\u0131', () => {\n    const items = [\n      { price: 50, quantity: 2 },\n      { price: 25, quantity: 3 }\n    ];\n    expect(calculateOrderTotal(items)).toBe(50 * 2 + 25 * 3); \/\/ 100 + 75 = 175\n  });\n\n  test('s\u0131f\u0131r fiyatl\u0131 \u00fcr\u00fcnleri do\u011fru i\u015flemeli', () => {\n    const items = [\n      { price: 0, quantity: 5 },\n      { price: 10, quantity: 1 }\n    ];\n    expect(calculateOrderTotal(items)).toBe(10);\n  });\n\n  test('negatif fiyatl\u0131 \u00fcr\u00fcnler i\u00e7in hata d\u00f6nd\u00fcrmese de do\u011fru toplam\u0131 hesaplamal\u0131 (i\u015f mant\u0131\u011f\u0131na ba\u011fl\u0131)', () => {\n    const items = [\n      { price: -10, quantity: 2 }, \/\/ Negatif fiyatlar ger\u00e7ek d\u00fcnyada olmamal\u0131, ama test ediyoruz\n      { price: 20, quantity: 1 }\n    ];\n    expect(calculateOrderTotal(items)).toBe(-20 + 20); \/\/ 0\n  });\n});\n  <\/code><\/pre>\n<\/div>\n<h3>5. Testleri \u00c7al\u0131\u015ft\u0131rma<\/h3>\n<p><code>package.json<\/code> dosyan\u0131za bir betik (script) ekleyerek testleri kolayca \u00e7al\u0131\u015ft\u0131rabilirsiniz:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ package.json\n{\n  \/\/ ... di\u011fer alanlar\n  \"scripts\": {\n    \"test\": \"jest\",\n    \"test:watch\": \"jest --watch\",\n    \"test:coverage\": \"jest --coverage\"\n  },\n  \/\/ ... di\u011fer alanlar\n}\n  <\/code><\/pre>\n<\/div>\n<p>\u015eimdi terminalde <code>npm test<\/code> komutunu \u00e7al\u0131\u015ft\u0131rarak testlerinizi \u00e7al\u0131\u015ft\u0131rabilirsiniz. \u00c7\u0131kt\u0131, testlerin ba\u015far\u0131 durumunu ve kod kapsam\u0131 raporunu g\u00f6sterecektir.<\/p>\n<p>Bu kurulumla, ajan\u0131n\u0131z\u0131n temel i\u015f mant\u0131\u011f\u0131n\u0131 izole edilmi\u015f bir \u015fekilde test etmeye ba\u015flayabilirsiniz. Bir sonraki ad\u0131m, d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131 olan daha karma\u015f\u0131k senaryolar\u0131 nas\u0131l ele alaca\u011f\u0131m\u0131z\u0131 \u00f6\u011frenmek olacakt\u0131r.<\/p>\n<h2>Ger\u00e7ek D\u00fcnya Senaryolar\u0131nda Ajan Testi: Vaka Analizleri ve Uygulamalar<\/h2>\n<p>Bir Google ADK TypeScript ajan\u0131n\u0131n ger\u00e7ek d\u00fcnya senaryolar\u0131nda nas\u0131l test edilece\u011fini anlamak, soyut test kavramlar\u0131n\u0131 somutla\u015ft\u0131rmak i\u00e7in \u00f6nemlidir. Bu b\u00f6l\u00fcmde, \u00fc\u00e7 farkl\u0131 vaka analizi \u00fczerinden ajan test stratejilerini uygulamal\u0131 olarak ele alaca\u011f\u0131z. Her senaryo, farkl\u0131 t\u00fcrde ba\u011f\u0131ml\u0131l\u0131klar ve i\u015f mant\u0131\u011f\u0131 i\u00e7erecek ve bu zorluklar\u0131n \u00fcstesinden gelmek i\u00e7in birim ve entegrasyon testlerinin nas\u0131l kullan\u0131labilece\u011fini g\u00f6sterecektir.<\/p>\n<h3>Vaka Analizi 1: E-ticaret Sipari\u015f Takip Ajan\u0131<\/h3>\n<p><strong>Senaryo:<\/strong> Bir e-ticaret platformu i\u00e7in geli\u015ftirilen bir chatbot ajan\u0131, kullan\u0131c\u0131n\u0131n sipari\u015f numaras\u0131n\u0131 alarak ilgili sipari\u015fin durumunu (\u00f6rne\u011fin, &#8220;Haz\u0131rlan\u0131yor&#8221;, &#8220;Kargoda&#8221;, &#8220;Teslim Edildi&#8221;) harici bir sipari\u015f y\u00f6netimi API&#8217;sinden sorgular ve kullan\u0131c\u0131ya geri bildirimde bulunur.<\/p>\n<p><strong>Test Edilmesi Gerekenler:<\/strong><\/p>\n<ol>\n<li>Sipari\u015f numaras\u0131n\u0131n ge\u00e7erlili\u011fi (format kontrol\u00fc).<\/li>\n<li>Harici API&#8217;ye yap\u0131lan \u00e7a\u011fr\u0131n\u0131n do\u011fru parametrelerle yap\u0131lmas\u0131.<\/li>\n<li>API&#8217;den gelen yan\u0131t\u0131n do\u011fru \u015fekilde i\u015flenmesi ve kullan\u0131c\u0131ya uygun mesaj\u0131n olu\u015fturulmas\u0131.<\/li>\n<li>API&#8217;nin hata d\u00f6nd\u00fcrmesi durumunda ajan\u0131n nas\u0131l tepki verdi\u011fi.<\/li>\n<\/ol>\n<p><strong>Uygulama ve Test Yakla\u015f\u0131m\u0131:<\/strong><\/p>\n<p>Bu senaryoda, ajan\u0131n i\u015f mant\u0131\u011f\u0131n\u0131 (sipari\u015f numaras\u0131n\u0131 do\u011frulama ve kullan\u0131c\u0131ya mesaj olu\u015fturma) harici API \u00e7a\u011fr\u0131s\u0131ndan ay\u0131rmal\u0131y\u0131z. API \u00e7a\u011fr\u0131s\u0131 k\u0131sm\u0131 entegrasyon testi ile, di\u011fer k\u0131s\u0131mlar birim testleri ile ele al\u0131nabilir.<\/p>\n<p><code>src\/orderService.ts<\/code> (Harici API ile etkile\u015fimi sim\u00fcle eden servis):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/orderService.ts\nexport interface OrderDetails {\n  orderId: string;\n  status: 'Haz\u0131rlan\u0131yor' | 'Kargoda' | 'Teslim Edildi' | '\u0130ptal Edildi';\n  estimatedDelivery?: string;\n}\n\nexport async function fetchOrderDetails(orderId: string): Promise<OrderDetails | null> {\n  \/\/ Ger\u00e7ek bir senaryoda burada harici bir API \u00e7a\u011fr\u0131s\u0131 olurdu\n  \/\/ \u00d6rne\u011fin: const response = await axios.get(<code>https:\/\/api.example.com\/orders\/${orderId}<\/code>);\n  \/\/ \u015eimdilik mock bir yan\u0131t d\u00f6nd\u00fcrelim:\n  if (orderId === '12345') {\n    return { orderId: '12345', status: 'Kargoda', estimatedDelivery: '2 g\u00fcn i\u00e7inde' };\n  }\n  if (orderId === '98765') {\n    return { orderId: '98765', status: 'Teslim Edildi' };\n  }\n  return null; \/\/ Sipari\u015f bulunamad\u0131\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/agentFunctions.ts<\/code> (Ajan\u0131n i\u015f mant\u0131\u011f\u0131):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/agentFunctions.ts\nimport { fetchOrderDetails, OrderDetails } from '.\/orderService';\n\nexport function isValidOrderId(orderId: string): boolean {\n  return \/^\\d{5}$\/.test(orderId); \/\/ 5 haneli say\u0131 oldu\u011funu varsayal\u0131m\n}\n\nexport async function getOrderStatusMessage(orderId: string): Promise<string> {\n  if (!isValidOrderId(orderId)) {\n    return 'L\u00fctfen ge\u00e7erli bir sipari\u015f numaras\u0131 girin (\u00f6rne\u011fin: 12345).';\n  }\n\n  const orderDetails = await fetchOrderDetails(orderId);\n\n  if (!orderDetails) {\n    return <code>&quot;${orderId}&quot; numaral\u0131 sipari\u015f bulunamad\u0131. L\u00fctfen tekrar kontrol edin.<\/code>;\n  }\n\n  let message = <code>Sipari\u015finiz (${orderDetails.orderId}) \u015fu anda &quot;${orderDetails.status}&quot; durumundad\u0131r.<\/code>;\n  if (orderDetails.estimatedDelivery) {\n    message += <code>Tahmini teslimat: ${orderDetails.estimatedDelivery}.<\/code>;\n  }\n  return message;\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/agentFunctions.test.ts<\/code> (Testler):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/agentFunctions.test.ts\nimport { isValidOrderId, getOrderStatusMessage } from '.\/agentFunctions';\nimport * as OrderService from '.\/orderService'; \/\/ orderService mod\u00fcl\u00fcn\u00fc mocklamak i\u00e7in\n\n\/\/ OrderService mod\u00fcl\u00fcn\u00fc tamamen mockluyoruz\njest.mock('.\/orderService');\n\ndescribe('isValidOrderId', () => {\n  test('ge\u00e7erli sipari\u015f numaras\u0131n\u0131 do\u011frulamal\u0131', () => {\n    expect(isValidOrderId('12345')).toBe(true);\n  });\n\n  test('ge\u00e7ersiz sipari\u015f numaras\u0131n\u0131 reddetmeli (yanl\u0131\u015f uzunluk)', () => {\n    expect(isValidOrderId('123')).toBe(false);\n    expect(isValidOrderId('123456')).toBe(false);\n  });\n\n  test('ge\u00e7ersiz sipari\u015f numaras\u0131n\u0131 reddetmeli (harf i\u00e7eriyor)', () => {\n    expect(isValidOrderId('abcde')).toBe(false);\n  });\n});\n\ndescribe('getOrderStatusMessage', () => {\n  \/\/ Her testten \u00f6nce mocklanm\u0131\u015f fonksiyonlar\u0131 temizle\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  test('ge\u00e7ersiz sipari\u015f numaras\u0131 i\u00e7in uyar\u0131 mesaj\u0131 d\u00f6nmeli', async () => {\n    const message = await getOrderStatusMessage('123');\n    expect(message).toBe('L\u00fctfen ge\u00e7erli bir sipari\u015f numaras\u0131 girin (\u00f6rne\u011fin: 12345).');\n    \/\/ fetchOrderDetails fonksiyonunun \u00e7a\u011fr\u0131lmad\u0131\u011f\u0131n\u0131 do\u011frula\n    expect(OrderService.fetchOrderDetails).not.toHaveBeenCalled();\n  });\n\n  test('sipari\u015f bulunamad\u0131\u011f\u0131nda uyar\u0131 mesaj\u0131 d\u00f6nmeli', async () => {\n    \/\/ fetchOrderDetails fonksiyonunu null d\u00f6nd\u00fcrecek \u015fekilde mockla\n    (OrderService.fetchOrderDetails as jest.Mock).mockResolvedValue(null);\n\n    const message = await getOrderStatusMessage('54321');\n    expect(message).toBe('\"54321\" numaral\u0131 sipari\u015f bulunamad\u0131. L\u00fctfen tekrar kontrol edin.');\n    expect(OrderService.fetchOrderDetails).toHaveBeenCalledWith('54321');\n  });\n\n  test('sipari\u015f durumu ve tahmini teslimat ile mesaj d\u00f6nmeli', async () => {\n    const mockOrder: OrderService.OrderDetails = {\n      orderId: '12345',\n      status: 'Kargoda',\n      estimatedDelivery: '2 g\u00fcn i\u00e7inde'\n    };\n    (OrderService.fetchOrderDetails as jest.Mock).mockResolvedValue(mockOrder);\n\n    const message = await getOrderStatusMessage('12345');\n    expect(message).toBe('Sipari\u015finiz (12345) \u015fu anda \"Kargoda\" durumundad\u0131r. Tahmini teslimat: 2 g\u00fcn i\u00e7inde.');\n    expect(OrderService.fetchOrderDetails).toHaveBeenCalledWith('12345');\n  });\n\n  test('sadece sipari\u015f durumu ile mesaj d\u00f6nmeli (tahmini teslimat yoksa)', async () => {\n    const mockOrder: OrderService.OrderDetails = {\n      orderId: '98765',\n      status: 'Teslim Edildi'\n    };\n    (OrderService.fetchOrderDetails as jest.Mock).mockResolvedValue(mockOrder);\n\n    const message = await getOrderStatusMessage('98765');\n    expect(message).toBe('Sipari\u015finiz (98765) \u015fu anda \"Teslim Edildi\" durumundad\u0131r.');\n    expect(OrderService.fetchOrderDetails).toHaveBeenCalledWith('98765');\n  });\n});\n  <\/code><\/pre>\n<\/div>\n<p>Bu \u00f6rnekte, <code>isValidOrderId<\/code> fonksiyonu tamamen ba\u011f\u0131ms\u0131z oldu\u011fu i\u00e7in birim testiyle kolayca test edilebilir. <code>getOrderStatusMessage<\/code> fonksiyonu ise <code>fetchOrderDetails<\/code>&#8216;e ba\u011f\u0131ml\u0131d\u0131r. Bu ba\u011f\u0131ml\u0131l\u0131\u011f\u0131, Jest&#8217;in <code>jest.mock<\/code> \u00f6zelli\u011fi ile sahte (mock) bir versiyonla de\u011fi\u015ftirerek, ger\u00e7ek API \u00e7a\u011fr\u0131s\u0131 yapmadan ajan\u0131n mant\u0131\u011f\u0131n\u0131 test edebiliyoruz. Bu, entegrasyon testi seviyesinde bir yakla\u015f\u0131md\u0131r, ancak d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 izole etti\u011fimiz i\u00e7in h\u0131zl\u0131 ve kontrol edilebilir kal\u0131r.<\/p>\n<h3>Vaka Analizi 2: M\u00fc\u015fteri Hizmetleri Chatbotu &#8211; S\u0131k\u00e7a Sorulan Sorular (SSS) Ajan\u0131<\/h3>\n<p><strong>Senaryo:<\/strong> Bir m\u00fc\u015fteri hizmetleri chatbotu, kullan\u0131c\u0131n\u0131n sordu\u011fu sorular\u0131 belirli anahtar kelimelerle e\u015fle\u015ftirerek \u00f6nceden tan\u0131mlanm\u0131\u015f SSS yan\u0131tlar\u0131n\u0131 d\u00f6nd\u00fcr\u00fcr. E\u011fer uygun bir SSS bulunamazsa, kullan\u0131c\u0131y\u0131 bir canl\u0131 temsilciye y\u00f6nlendirir.<\/p>\n<p><strong>Test Edilmesi Gerekenler:<\/strong><\/p>\n<ol>\n<li>Farkl\u0131 kullan\u0131c\u0131 sorular\u0131 i\u00e7in do\u011fru SSS yan\u0131t\u0131n\u0131n e\u015fle\u015ftirilmesi.<\/li>\n<li>Anahtar kelime e\u015fle\u015fmesi olmad\u0131\u011f\u0131nda canl\u0131 temsilciye y\u00f6nlendirme mekanizmas\u0131n\u0131n tetiklenmesi.<\/li>\n<li>B\u00fcy\u00fck\/k\u00fc\u00e7\u00fck harf duyarl\u0131l\u0131\u011f\u0131 veya benzeri kenar durumlar.<\/li>\n<\/ol>\n<p><strong>Uygulama ve Test Yakla\u015f\u0131m\u0131:<\/strong><\/p>\n<p>Bu ajan, \u00f6zellikle metin i\u015fleme ve e\u015fle\u015ftirme mant\u0131\u011f\u0131na odaklan\u0131r. \u0130\u015f mant\u0131\u011f\u0131n\u0131 izole edip, sadece bu mant\u0131\u011f\u0131 test edebiliriz.<\/p>\n<p><code>src\/faqService.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/faqService.ts\nexport interface FAQItem {\n  keywords: string[];\n  answer: string;\n}\n\nconst faqs: FAQItem[] = [\n  { keywords: ['sipari\u015f', 'takip'], answer: 'Sipari\u015finizi takip etmek i\u00e7in sipari\u015f numaran\u0131z\u0131 girmeniz yeterlidir.' },\n  { keywords: ['iade', '\u00fcr\u00fcn'], answer: '\u0130ade i\u015flemleri i\u00e7in l\u00fctfen iade politikam\u0131z\u0131 inceleyin veya m\u00fc\u015fteri hizmetleri ile ileti\u015fime ge\u00e7in.' },\n  { keywords: ['kargo', 'teslimat'], answer: 'Kargo ve teslimat s\u00fcreleri \u00fcr\u00fcn\u00fcn\u00fcze ve adresinize g\u00f6re de\u011fi\u015fiklik g\u00f6sterebilir.' },\n];\n\nexport function findFAQAnswer(question: string): string | null {\n  const lowerCaseQuestion = question.toLowerCase();\n  for (const faq of faqs) {\n    if (faq.keywords.some(keyword => lowerCaseQuestion.includes(keyword))) {\n      return faq.answer;\n    }\n  }\n  return null;\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/faqService.test.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/faqService.test.ts\nimport { findFAQAnswer } from '.\/faqService';\n\ndescribe('findFAQAnswer', () => {\n  test('sipari\u015f ile ilgili soruya do\u011fru yan\u0131t d\u00f6nmeli', () => {\n    expect(findFAQAnswer('sipari\u015fimi takip edebilir miyim?')).toBe('Sipari\u015finizi takip etmek i\u00e7in sipari\u015f numaran\u0131z\u0131 girmeniz yeterlidir.');\n  });\n\n  test('iade ile ilgili soruya do\u011fru yan\u0131t d\u00f6nmeli', () => {\n    expect(findFAQAnswer('\u00fcr\u00fcn iadesi nas\u0131l yapabilirim?')).toBe('\u0130ade i\u015flemleri i\u00e7in l\u00fctfen iade politikam\u0131z\u0131 inceleyin veya m\u00fc\u015fteri hizmetleri ile ileti\u015fime ge\u00e7in.');\n  });\n\n  test('b\u00fcy\u00fck\/k\u00fc\u00e7\u00fck harf duyarl\u0131l\u0131\u011f\u0131n\u0131 do\u011fru i\u015flemeli', () => {\n    expect(findFAQAnswer('S\u0130PAR\u0130\u015e\u0130M nerede?')).toBe('Sipari\u015finizi takip etmek i\u00e7in sipari\u015f numaran\u0131z\u0131 girmeniz yeterlidir.');\n  });\n\n  test('e\u015fle\u015fme bulunamad\u0131\u011f\u0131nda null d\u00f6nmeli', () => {\n    expect(findFAQAnswer('\u00fcr\u00fcnleriniz kaliteli mi?')).toBeNull();\n  });\n\n  test('birden fazla anahtar kelime i\u00e7eren soruya ilk e\u015fle\u015fen yan\u0131t\u0131 d\u00f6nmeli', () => {\n    \/\/ 'sipari\u015f' ve 'iade' i\u00e7eren bir soru, 'sipari\u015f' \u00f6nce e\u015fle\u015fti\u011fi i\u00e7in onun yan\u0131t\u0131 gelmeli\n    expect(findFAQAnswer('sipari\u015fimi iade etmek istiyorum')).toBe('Sipari\u015finizi takip etmek i\u00e7in sipari\u015f numaran\u0131z\u0131 girmeniz yeterlidir.');\n  });\n});\n  <\/code><\/pre>\n<\/div>\n<p>Bu senaryoda, <code>findFAQAnswer<\/code> fonksiyonu saf bir fonksiyon oldu\u011fu i\u00e7in d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131\u011f\u0131 yoktur ve do\u011frudan birim testleriyle test edilebilir. Bu, ajan\u0131n \u00e7ekirdek mant\u0131\u011f\u0131n\u0131n h\u0131zl\u0131 ve g\u00fcvenilir bir \u015fekilde do\u011frulanmas\u0131n\u0131 sa\u011flar.<\/p>\n<h3>Vaka Analizi 3: Veri Toplama Ajan\u0131 &#8211; Form Doldurma<\/h3>\n<p><strong>Senaryo:<\/strong> Bir ajan, kullan\u0131c\u0131lardan ad, soyad, e-posta gibi bilgileri ad\u0131m ad\u0131m toplayarak bir kay\u0131t formu doldurur. Her ad\u0131mda kullan\u0131c\u0131n\u0131n girdi\u011fi verinin ge\u00e7erlili\u011fini kontrol eder.<\/p>\n<p><strong>Test Edilmesi Gerekenler:<\/strong><\/p>\n<ol>\n<li>Her bir veri alan\u0131n\u0131n (ad, e-posta vb.) do\u011frulama kurallar\u0131.<\/li>\n<li>Kullan\u0131c\u0131ya yanl\u0131\u015f giri\u015flerde uygun hata mesajlar\u0131n\u0131n verilmesi.<\/li>\n<li>T\u00fcm veriler topland\u0131\u011f\u0131nda kay\u0131t i\u015fleminin tetiklenmesi (mock bir servise).<\/li>\n<\/ol>\n<p><strong>Uygulama ve Test Yakla\u015f\u0131m\u0131:<\/strong><\/p>\n<p>Bu senaryoda, her bir veri alan\u0131n\u0131n do\u011frulama mant\u0131\u011f\u0131 birim testleriyle, kay\u0131t i\u015flemini tetikleyen k\u0131s\u0131m ise entegrasyon testiyle ele al\u0131nabilir.<\/p>\n<p><code>src\/validationService.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/validationService.ts\nexport function isValidEmail(email: string): boolean {\n  return \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(email);\n}\n\nexport function isValidName(name: string): boolean {\n  return name.trim().length > 2;\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/registrationAgent.ts<\/code> (Ajan\u0131n kay\u0131t mant\u0131\u011f\u0131):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/registrationAgent.ts\nimport { isValidEmail, isValidName } from '.\/validationService';\n\nexport interface UserRegistrationData {\n  name: string;\n  email: string;\n}\n\n\/\/ Mock bir kay\u0131t servisi\nasync function registerUser(data: UserRegistrationData): Promise<{ success: boolean; message: string }> {\n  return new Promise((resolve) => {\n    setTimeout(() => {\n      if (data.email.includes('error')) {\n        resolve({ success: false, message: 'Kay\u0131t ba\u015far\u0131s\u0131z oldu: E-posta zaten kullan\u0131mda.' });\n      } else {\n        resolve({ success: true, message: <code>Kullan\u0131c\u0131 ${data.name} ba\u015far\u0131yla kaydedildi.<\/code> });\n      }\n    }, 100); \/\/ Asenkron bir i\u015flem sim\u00fclasyonu\n  });\n}\n\nexport async function processRegistration(name: string, email: string): Promise<string> {\n  if (!isValidName(name)) {\n    return 'L\u00fctfen ge\u00e7erli bir isim girin.';\n  }\n  if (!isValidEmail(email)) {\n    return 'L\u00fctfen ge\u00e7erli bir e-posta adresi girin.';\n  }\n\n  const result = await registerUser({ name, email });\n  if (result.success) {\n    return result.message;\n  } else {\n    return <code>Kay\u0131t i\u015flemi s\u0131ras\u0131nda bir hata olu\u015ftu: ${result.message}<\/code>;\n  }\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/registrationAgent.test.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/registrationAgent.test.ts\nimport { processRegistration } from '.\/registrationAgent';\nimport * as ValidationService from '.\/validationService';\n\n\/\/ ValidationService'i mocklam\u0131yoruz \u00e7\u00fcnk\u00fc saf fonksiyonlar ve do\u011frudan test edilebilirler.\n\/\/ Ancak registerUser fonksiyonunu i\u00e7eren registrationAgent mod\u00fcl\u00fcndeki registerUser'\u0131 mocklayabiliriz.\n\n\/\/ processRegistration i\u00e7inde \u00e7a\u011fr\u0131lan registerUser fonksiyonunu mocklamak i\u00e7in\n\/\/ do\u011frudan processRegistration'\u0131 i\u00e7eren dosyay\u0131 import edip i\u00e7indeki fonksiyonu spyOn ile mocklayabiliriz.\n\/\/ Ancak daha iyi bir yakla\u015f\u0131m, registerUser'\u0131 ayr\u0131 bir mod\u00fcl olarak d\u0131\u015fa aktarmak ve onu mocklamakt\u0131r.\n\/\/ Bu \u00f6rnekte, processRegistration i\u00e7inde yerle\u015fik bir fonksiyon gibi davranan registerUser'\u0131\n\/\/ ayr\u0131 bir mock edilebilir servis olarak d\u00fc\u015f\u00fcnelim veya do\u011frudan processRegistration'\u0131 test edelim.\n\ndescribe('processRegistration', () => {\n  \/\/ isValidName ve isValidEmail fonksiyonlar\u0131n\u0131 mocklayabiliriz, ancak bu \u00f6rnekte\n  \/\/ do\u011frudan \u00e7a\u011fr\u0131l\u0131p sonu\u00e7lar\u0131na g\u00f6re test edece\u011fiz.\n  \/\/ Ger\u00e7ek bir senaryoda, registerUser'\u0131 mocklamak daha yayg\u0131n olacakt\u0131r.\n\n  test('ge\u00e7ersiz isim i\u00e7in hata mesaj\u0131 d\u00f6nmeli', async () => {\n    const result = await processRegistration('a', 'test@example.com');\n    expect(result).toBe('L\u00fctfen ge\u00e7erli bir isim girin.');\n  });\n\n  test('ge\u00e7ersiz e-posta i\u00e7in hata mesaj\u0131 d\u00f6nmeli', async () => {\n    const result = await processRegistration('Ali Can', 'invalid-email');\n    expect(result).toBe('L\u00fctfen ge\u00e7erli bir e-posta adresi girin.');\n  });\n\n  test('ba\u015far\u0131l\u0131 kay\u0131t i\u00e7in onay mesaj\u0131 d\u00f6nmeli', async () => {\n    \/\/ Burada registerUser'\u0131 mocklam\u0131\u015f gibi davran\u0131yoruz.\n    \/\/ Ger\u00e7ek bir senaryoda, registerUser'\u0131 d\u0131\u015fa aktar\u0131p jest.mock ile mocklard\u0131k.\n    const result = await processRegistration('Ay\u015fe Y\u0131lmaz', 'ayse@example.com');\n    expect(result).toBe('Kullan\u0131c\u0131 Ay\u015fe Y\u0131lmaz ba\u015far\u0131yla kaydedildi.');\n  });\n\n  test('kay\u0131t servisi hata d\u00f6nd\u00fcrd\u00fc\u011f\u00fcnde hata mesaj\u0131 d\u00f6nmeli', async () => {\n    \/\/ Hata durumunu sim\u00fcle etmek i\u00e7in \u00f6zel bir e-posta kullan\u0131yoruz\n    const result = await processRegistration('Hata Test', 'error@example.com');\n    expect(result).toBe('Kay\u0131t i\u015flemi s\u0131ras\u0131nda bir hata olu\u015ftu: Kay\u0131t ba\u015far\u0131s\u0131z oldu: E-posta zaten kullan\u0131mda.');\n  });\n});\n  <\/code><\/pre>\n<\/div>\n<p>Bu vaka analizleri, ajanlar\u0131n\u0131z\u0131n farkl\u0131 bile\u015fenlerini nas\u0131l izole edece\u011finizi ve bunlar\u0131 birim veya entegrasyon testleriyle nas\u0131l kapsayaca\u011f\u0131n\u0131z\u0131 g\u00f6stermektedir. Ba\u011f\u0131ml\u0131l\u0131klar\u0131 mocklamak, testlerin h\u0131zl\u0131 ve g\u00fcvenilir kalmas\u0131n\u0131 sa\u011flarken, ajan\u0131n temel i\u015flevselli\u011fini ve d\u0131\u015f servislerle etkile\u015fimini do\u011frular. Bir sonraki b\u00f6l\u00fcmde, bu test tekniklerini daha da ileriye ta\u015f\u0131yacak geli\u015fmi\u015f y\u00f6ntemlere odaklanaca\u011f\u0131z.<\/p>\n<h2>\u0130leri D\u00fczey Test Teknikleri: Mocking, Stubbing ve Spy Kullan\u0131m\u0131<\/h2>\n<p>Google ADK TypeScript ajanlar\u0131 genellikle karma\u015f\u0131k d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klarla (API&#8217;ler, veritabanlar\u0131, di\u011fer Google Cloud servisleri) etkile\u015fim kurar ve asenkron i\u015flemler ger\u00e7ekle\u015ftirir. Bu t\u00fcr senaryolarda, sadece birim testleri yeterli olmayabilir. \u0130leri d\u00fczey test teknikleri olan mocking, stubbing ve spy kullan\u0131m\u0131, bu ba\u011f\u0131ml\u0131l\u0131klar\u0131 kontrol alt\u0131na alman\u0131za ve asenkron kodunuzu g\u00fcvenilir bir \u015fekilde test etmenize olanak tan\u0131r. Jest test \u00e7er\u00e7evesi, bu teknikleri uygulamak i\u00e7in g\u00fc\u00e7l\u00fc ara\u00e7lar sunar.<\/p>\n<h3>Mocking (Sahte Nesne Olu\u015fturma)<\/h3>\n<p>Mocking, bir ba\u011f\u0131ml\u0131l\u0131\u011f\u0131n (\u00f6rne\u011fin, bir servis veya mod\u00fcl) ger\u00e7ek uygulamas\u0131n\u0131, test s\u0131ras\u0131nda kontrol edebilece\u011finiz sahte bir versiyonla de\u011fi\u015ftirmek anlam\u0131na gelir. Mock&#8217;lar sadece belirli bir de\u011feri d\u00f6nd\u00fcrmekle kalmaz, ayn\u0131 zamanda kendilerine yap\u0131lan \u00e7a\u011fr\u0131lar\u0131 da kaydedebilirler (ka\u00e7 kez \u00e7a\u011fr\u0131ld\u0131, hangi arg\u00fcmanlarla \u00e7a\u011fr\u0131ld\u0131 vb.). Bu, bir fonksiyonun d\u0131\u015f bir servisle do\u011fru \u015fekilde etkile\u015fim kurup kurmad\u0131\u011f\u0131n\u0131 do\u011frulamak i\u00e7in \u00e7ok kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<p><strong>Jest ile Mod\u00fcl Mocklama:<\/strong><\/p>\n<p>Diyelim ki bir ajan\u0131n Google Cloud Firestore ile etkile\u015fime giren bir <code>dataService.ts<\/code> mod\u00fcl\u00fc var. Bu mod\u00fcl\u00fc test ederken ger\u00e7ek Firestore&#8217;a ba\u011flanmak istemeyiz.<\/p>\n<p><code>src\/dataService.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/dataService.ts\n\/\/ Ger\u00e7ek bir senaryoda burada Firebase Admin SDK veya Google Cloud Firestore SDK kullan\u0131lacakt\u0131.\n\/\/ import { Firestore } from '@google-cloud\/firestore';\n\/\/ const db = new Firestore();\n\nexport async function getUserData(userId: string): Promise<{ name: string; email: string } | null> {\n  \/\/ Ger\u00e7ek Firestore sorgusu burada olurdu\n  \/\/ const docRef = db.collection('users').doc(userId);\n  \/\/ const doc = await docRef.get();\n  \/\/ return doc.exists ? doc.data() as { name: string; email: string } : null;\n  return new Promise(resolve => setTimeout(() => {\n    if (userId === 'user123') {\n      resolve({ name: 'Ahmet Y\u0131lmaz', email: 'ahmet@example.com' });\n    } else {\n      resolve(null);\n    }\n  }, 50));\n}\n\nexport async function updateUserData(userId: string, data: { name?: string; email?: string }): Promise<void> {\n  \/\/ Ger\u00e7ek Firestore g\u00fcncelleme i\u015flemi burada olurdu\n  \/\/ await db.collection('users').doc(userId).update(data);\n  return new Promise(resolve => setTimeout(resolve, 50));\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/agentHandler.ts<\/code> (Ajan\u0131n bu servisi kulland\u0131\u011f\u0131 yer):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/agentHandler.ts\nimport { getUserData, updateUserData } from '.\/dataService';\n\nexport async function handleUserProfileRequest(userId: string): Promise<string> {\n  const userData = await getUserData(userId);\n  if (!userData) {\n    return 'Kullan\u0131c\u0131 profili bulunamad\u0131.';\n  }\n  return <code>Kullan\u0131c\u0131 Ad\u0131: ${userData.name}, E-posta: ${userData.email}<\/code>;\n}\n\nexport async function updateUserName(userId: string, newName: string): Promise<string> {\n  await updateUserData(userId, { name: newName });\n  return <code>Kullan\u0131c\u0131 ${userId} i\u00e7in isim &quot;${newName}&quot; olarak g\u00fcncellendi.<\/code>;\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/agentHandler.test.ts<\/code> (Test dosyas\u0131):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/agentHandler.test.ts\nimport { handleUserProfileRequest, updateUserName } from '.\/agentHandler';\nimport * as DataService from '.\/dataService'; \/\/ Mocklamak istedi\u011fimiz mod\u00fcl\n\n\/\/ dataService mod\u00fcl\u00fcn\u00fc mockluyoruz\njest.mock('.\/dataService');\n\ndescribe('handleUserProfileRequest', () => {\n  beforeEach(() => {\n    jest.clearAllMocks(); \/\/ Her testten \u00f6nce mock \u00e7a\u011fr\u0131lar\u0131n\u0131 temizle\n  });\n\n  test('kullan\u0131c\u0131 verisi bulundu\u011funda do\u011fru mesaj\u0131 d\u00f6nmeli', async () => {\n    \/\/ getUserData fonksiyonunun mocklanm\u0131\u015f davran\u0131\u015f\u0131n\u0131 tan\u0131mla\n    (DataService.getUserData as jest.Mock).mockResolvedValue({ name: 'Deniz', email: 'deniz@example.com' });\n\n    const message = await handleUserProfileRequest('user456');\n    expect(message).toBe('Kullan\u0131c\u0131 Ad\u0131: Deniz, E-posta: deniz@example.com');\n    expect(DataService.getUserData).toHaveBeenCalledWith('user456'); \/\/ Do\u011fru arg\u00fcmanla \u00e7a\u011fr\u0131ld\u0131\u011f\u0131n\u0131 kontrol et\n    expect(DataService.getUserData).toHaveBeenCalledTimes(1); \/\/ Bir kez \u00e7a\u011fr\u0131ld\u0131\u011f\u0131n\u0131 kontrol et\n  });\n\n  test('kullan\u0131c\u0131 verisi bulunamad\u0131\u011f\u0131nda uygun mesaj\u0131 d\u00f6nmeli', async () => {\n    (DataService.getUserData as jest.Mock).mockResolvedValue(null); \/\/ Null d\u00f6necek \u015fekilde mockla\n\n    const message = await handleUserProfileRequest('nonexistentUser');\n    expect(message).toBe('Kullan\u0131c\u0131 profili bulunamad\u0131.');\n    expect(DataService.getUserData).toHaveBeenCalledWith('nonexistentUser');\n  });\n});\n\ndescribe('updateUserName', () => {\n  beforeEach(() => {\n    jest.clearAllMocks();\n  });\n\n  test('kullan\u0131c\u0131 ad\u0131 ba\u015far\u0131yla g\u00fcncellendi\u011finde onay mesaj\u0131 d\u00f6nmeli', async () => {\n    \/\/ updateUserData fonksiyonunun mocklanm\u0131\u015f davran\u0131\u015f\u0131n\u0131 tan\u0131mla\n    (DataService.updateUserData as jest.Mock).mockResolvedValue(undefined); \/\/ void bir fonksiyon mock'u\n\n    const message = await updateUserName('user789', 'Yeni \u0130sim');\n    expect(message).toBe('Kullan\u0131c\u0131 user789 i\u00e7in isim \"Yeni \u0130sim\" olarak g\u00fcncellendi.');\n    expect(DataService.updateUserData).toHaveBeenCalledWith('user789', { name: 'Yeni \u0130sim' });\n    expect(DataService.updateUserData).toHaveBeenCalledTimes(1);\n  });\n});\n  <\/code><\/pre>\n<\/div>\n<h3>Stubbing (Taklit Nesne Olu\u015fturma)<\/h3>\n<p>Stubbing, bir fonksiyonun veya metodun belirli bir girdi i\u00e7in sabit bir \u00e7\u0131kt\u0131 d\u00f6nd\u00fcrmesini sa\u011flamakt\u0131r. Mocking&#8217;e benzerdir ancak stub&#8217;lar genellikle \u00e7a\u011fr\u0131 ge\u00e7mi\u015fini kaydetmez veya di\u011fer davran\u0131\u015flar\u0131 kontrol etmez. Sadece belirli bir sonu\u00e7 d\u00f6nd\u00fcrmekle ilgilenirler. Jest&#8217;te <code>jest.fn().mockReturnValue()<\/code> veya <code>.mockResolvedValue()<\/code> gibi y\u00f6ntemlerle stub&#8217;lar olu\u015fturulabilir.<\/p>\n<p>Yukar\u0131daki \u00f6rnekte <code>(DataService.getUserData as jest.Mock).mockResolvedValue(...)<\/code> asl\u0131nda bir stubbing \u00f6rne\u011fidir; belirli bir senaryo i\u00e7in belirli bir de\u011fer d\u00f6nd\u00fcrmesini sa\u011fl\u0131yoruz.<\/p>\n<h3>Spies (Casus Fonksiyonlar)<\/h3>\n<p>Spy&#8217;lar, mevcut bir fonksiyonu de\u011fi\u015ftirmeden ona yap\u0131lan \u00e7a\u011fr\u0131lar\u0131 izlemenize olanak tan\u0131r. Bir fonksiyonun \u00e7a\u011fr\u0131l\u0131p \u00e7a\u011fr\u0131lmad\u0131\u011f\u0131n\u0131, ka\u00e7 kez \u00e7a\u011fr\u0131ld\u0131\u011f\u0131n\u0131 ve hangi arg\u00fcmanlarla \u00e7a\u011fr\u0131ld\u0131\u011f\u0131n\u0131 kontrol etmek istedi\u011finizde kullan\u0131\u015fl\u0131d\u0131r. Ger\u00e7ek fonksiyonun \u00e7al\u0131\u015fmas\u0131na izin verirken, ayn\u0131 zamanda onun \u00fczerindeki etkile\u015fimi de g\u00f6zlemlersiniz.<\/p>\n<p><strong>Jest ile Spy Kullan\u0131m\u0131:<\/strong><\/p>\n<p>Diyelim ki bir ajan\u0131n bir hata durumunda bir loglama fonksiyonunu \u00e7a\u011f\u0131rd\u0131\u011f\u0131ndan emin olmak istiyoruz, ancak ger\u00e7ek loglama i\u015fleminin test s\u0131ras\u0131nda ger\u00e7ekle\u015fmesini istemiyoruz.<\/p>\n<p><code>src\/logger.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/logger.ts\nexport function logError(message: string, context?: any) {\n  console.error(<code>ERROR: ${message}<\/code>, context);\n  \/\/ Ger\u00e7ek bir uygulamada burada bir loglama servisine (Cloud Logging vb.) g\u00f6nderim olurdu.\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/errorAgent.ts<\/code> (Hata durumunda loglama yapan ajan):<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/errorAgent.ts\nimport { logError } from '.\/logger';\n\nexport function processCriticalOperation(data: any): string {\n  if (!data || !data.isValid) {\n    logError('Kritik i\u015flem i\u00e7in ge\u00e7ersiz veri al\u0131nd\u0131.', { data });\n    return '\u0130\u015flem ba\u015far\u0131s\u0131z oldu: Ge\u00e7ersiz veri.';\n  }\n  \/\/ Ba\u015far\u0131l\u0131 i\u015flem mant\u0131\u011f\u0131\n  return '\u0130\u015flem ba\u015far\u0131yla tamamland\u0131.';\n}\n  <\/code><\/pre>\n<\/div>\n<p><code>src\/errorAgent.test.ts<\/code>:<\/p>\n<div class=\"code-container\">\n<pre><code>\n\/\/ src\/errorAgent.test.ts\nimport { processCriticalOperation } from '.\/errorAgent';\nimport * as Logger from '.\/logger'; \/\/ Spy'layaca\u011f\u0131m\u0131z mod\u00fcl\n\ndescribe('processCriticalOperation', () => {\n  let logErrorSpy: jest.SpyInstance;\n\n  beforeEach(() => {\n    \/\/ Logger.logError fonksiyonunu spy'la\n    logErrorSpy = jest.spyOn(Logger, 'logError');\n    logErrorSpy.mockImplementation(() => {}); \/\/ Ger\u00e7ek loglama i\u015flemini engelle\n  });\n\n  afterEach(() => {\n    logErrorSpy.mockRestore(); \/\/ Spy'\u0131 orijinal haline geri d\u00f6nd\u00fcr\n  });\n\n  test('ge\u00e7ersiz veri ile \u00e7a\u011fr\u0131ld\u0131\u011f\u0131nda hata loglamal\u0131 ve uygun mesaj\u0131 d\u00f6nmeli', () => {\n    const result = processCriticalOperation({ isValid: false });\n    expect(result).toBe('\u0130\u015flem ba\u015far\u0131s\u0131z oldu: Ge\u00e7ersiz veri.');\n    expect(logErrorSpy).toHaveBeenCalledTimes(1);\n    expect(logErrorSpy).toHaveBeenCalledWith('Kritik i\u015flem i\u00e7in ge\u00e7ersiz veri al\u0131nd\u0131.', { data: { isValid: false } });\n  });\n\n  test('ge\u00e7erli veri ile \u00e7a\u011fr\u0131ld\u0131\u011f\u0131nda hata loglamamal\u0131 ve ba\u015far\u0131l\u0131 mesaj\u0131 d\u00f6nmeli', () => {\n    const result = processCriticalOperation({ isValid: true });\n    expect(result).toBe('\u0130\u015flem ba\u015far\u0131yla tamamland\u0131.');\n    expect(logErrorSpy).not.toHaveBeenCalled(); \/\/ Hata loglanmamal\u0131\n  });\n});\n  <\/code><\/pre>\n<\/div>\n<p>Bu \u00f6rnekte, <code>jest.spyOn<\/code> ile <code>Logger.logError<\/code> fonksiyonunu izliyoruz. <code>mockImplementation(() => {})<\/code> ile ger\u00e7ek <code>console.error<\/code> \u00e7a\u011fr\u0131s\u0131n\u0131 engelliyoruz, b\u00f6ylece test \u00e7\u0131kt\u0131m\u0131z kirlenmiyor. <code>toHaveBeenCalled<\/code> gibi matcher&#8217;lar ile fonksiyonun do\u011fru \u015fekilde \u00e7a\u011fr\u0131l\u0131p \u00e7a\u011fr\u0131lmad\u0131\u011f\u0131n\u0131 kontrol ediyoruz.<\/p>\n<h3>Asenkron Kodun Etkin Testi<\/h3>\n<p>ADK ajanlar\u0131 s\u0131kl\u0131kla asenkron i\u015flemlerle u\u011fra\u015f\u0131r (API \u00e7a\u011fr\u0131lar\u0131, veritaban\u0131 i\u015flemleri). Jest, asenkron testleri kolayla\u015ft\u0131rmak i\u00e7in \u00e7e\u015fitli y\u00f6ntemler sunar:<\/p>\n<ul>\n<li><strong>Promises:<\/strong> <code>async\/await<\/code> veya <code>.then().catch()<\/code> zincirlerini kullanarak testler yazabilirsiniz. Jest, bir testin Promise d\u00f6nd\u00fcrd\u00fc\u011f\u00fcn\u00fc otomatik olarak alg\u0131lar ve Promise \u00e7\u00f6z\u00fcmlenene kadar bekler.<\/li>\n<li><strong><code>.resolves<\/code> \/ <code>.rejects<\/code> Matcher&#8217;lar\u0131:<\/strong> Bir Promise&#8217;in ba\u015far\u0131yla \u00e7\u00f6z\u00fcmlenmesini veya reddedilmesini do\u011frudan beklemek i\u00e7in bu matcher&#8217;lar\u0131 kullanabilirsiniz.<\/li>\n<\/ul>\n<div class=\"code-container\">\n<pre><code>\n\/\/ Asenkron fonksiyon \u00f6rne\u011fi\nasync function fetchData(): Promise<string> {\n  return new Promise(resolve => setTimeout(() => resolve('Veri ba\u015far\u0131yla \u00e7ekildi.'), 100));\n}\n\n\/\/ Test\ntest('asenkron veri \u00e7ekme ba\u015far\u0131l\u0131 olmal\u0131', async () => {\n  await expect(fetchData()).resolves.toBe('Veri ba\u015far\u0131yla \u00e7ekildi.');\n});\n\nasync function fetchFailingData(): Promise<string> {\n  return new Promise((_, reject) => setTimeout(() => reject(new Error('Veri \u00e7ekme hatas\u0131.')), 100));\n}\n\ntest('asenkron veri \u00e7ekme ba\u015far\u0131s\u0131z olmal\u0131', async () => {\n  await expect(fetchFailingData()).rejects.toThrow('Veri \u00e7ekme hatas\u0131.');\n});\n  <\/code><\/pre>\n<\/div>\n<p>Bu ileri d\u00fczey teknikler, ajanlar\u0131n\u0131z\u0131n karma\u015f\u0131k ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131 ve asenkron do\u011fas\u0131n\u0131 kontrol alt\u0131na alman\u0131za yard\u0131mc\u0131 olur, b\u00f6ylece testleriniz daha g\u00fcvenilir, h\u0131zl\u0131 ve kapsaml\u0131 hale gelir. Bu teknikleri ustaca kullanarak, &#8220;c\u00fcmleleri kovalamak&#8221; yerine ajan\u0131n \u00e7ekirdek mant\u0131\u011f\u0131na odaklanabilirsiniz.<\/p>\n<h2>Sonu\u00e7 ve S\u0131k\u00e7a Sorulan Sorular<\/h2>\n<p>Google ADK TypeScript ajanlar\u0131n\u0131 test etmek, modern yaz\u0131l\u0131m geli\u015ftirme s\u00fcre\u00e7lerinin ayr\u0131lmaz bir par\u00e7as\u0131d\u0131r ve &#8220;c\u00fcmleleri kovalamadan&#8221; etkin bir \u015fekilde yap\u0131labilir. Bu makale boyunca, TypeScript&#8217;in tip g\u00fcvenli\u011fi ve mod\u00fcler yap\u0131s\u0131n\u0131n ajan geli\u015ftirme ve test etme s\u00fcre\u00e7lerine nas\u0131l de\u011fer katt\u0131\u011f\u0131n\u0131, birim, entegrasyon ve u\u00e7tan uca test stratejilerinin nas\u0131l uygulanaca\u011f\u0131n\u0131 ve Jest gibi g\u00fc\u00e7l\u00fc bir test \u00e7er\u00e7evesiyle ileri d\u00fczey mocking, stubbing ve spy tekniklerinin nas\u0131l kullan\u0131laca\u011f\u0131n\u0131 detayl\u0131 bir \u015fekilde inceledik. Ger\u00e7ek d\u00fcnya senaryolar\u0131 \u00fczerinden sundu\u011fumuz vaka analizleri, soyut kavramlar\u0131 somutla\u015ft\u0131rman\u0131za ve kendi projelerinizde benzer yakla\u015f\u0131mlar\u0131 uygulaman\u0131za yard\u0131mc\u0131 olmay\u0131 hedeflemi\u015ftir.<\/p>\n<p>Unutmay\u0131n ki sa\u011flam bir test s\u00fcreci, sadece hatalar\u0131 erken a\u015famada yakalamakla kalmaz, ayn\u0131 zamanda kod kalitesini art\u0131r\u0131r, geli\u015ftirme h\u0131z\u0131n\u0131 y\u00fckseltir ve gelecekteki de\u011fi\u015fiklikler i\u00e7in bir g\u00fcvenlik a\u011f\u0131 olu\u015fturur. Ajanlar\u0131n\u0131z\u0131n i\u015f mant\u0131\u011f\u0131n\u0131 d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klardan ay\u0131rarak, saf fonksiyonlar yazarak ve bu ba\u011f\u0131ml\u0131l\u0131klar\u0131 test ortam\u0131nda ak\u0131ll\u0131ca mocklayarak, &#8220;c\u00fcmleleri kovalamak&#8221; zorunda kalmadan, ajanlar\u0131n\u0131z\u0131n beklenen \u015fekilde \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olabilirsiniz. Bu yakla\u015f\u0131m, daha g\u00fcvenilir, bak\u0131m\u0131 kolay ve \u00f6l\u00e7eklenebilir Google ADK TypeScript ajanlar\u0131 geli\u015ftirmenizin temelini olu\u015fturacakt\u0131r. Testlerinizi s\u00fcrekli olarak g\u00fcncel tutmak ve CI\/CD (S\u00fcrekli Entegrasyon\/S\u00fcrekli Da\u011f\u0131t\u0131m) s\u00fcre\u00e7lerinize entegre etmek, bu faydalar\u0131 maksimize etmenizi sa\u011flayacakt\u0131r.<\/p>\n<h3>S\u0131k\u00e7a Sorulan Sorular<\/h3>\n<h4>Soru 1: ADK TypeScript ajanlar\u0131 i\u00e7in hangi test \u00e7er\u00e7evesini \u00f6nerirsiniz?<\/h4>\n<p><strong>Cevap:<\/strong> Google ADK TypeScript ajanlar\u0131 i\u00e7in Jest, sundu\u011fu kapsaml\u0131 \u00f6zellikler, h\u0131zl\u0131 performans, kolay yap\u0131land\u0131rma ve g\u00fc\u00e7l\u00fc mocking yetenekleri nedeniyle en \u00e7ok \u00f6nerilen test \u00e7er\u00e7evesidir. TypeScript ile m\u00fckemmel uyum sa\u011flar ve asenkron kod testini basitle\u015ftirir. Alternatif olarak Mocha veya Vitest gibi \u00e7er\u00e7eveler de kullan\u0131labilir, ancak Jest genellikle ilk tercih olur.<\/p>\n<h4>Soru 2: Entegrasyon testlerinde d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131 nas\u0131l y\u00f6netmeliyim?<\/h4>\n<p><strong>Cevap:<\/strong> Entegrasyon testlerinde d\u0131\u015f ba\u011f\u0131ml\u0131l\u0131klar\u0131 (veritabanlar\u0131, harici API&#8217;ler, Google Cloud servisleri) y\u00f6netmek i\u00e7in mocking ve stubbing tekniklerini kullanmal\u0131s\u0131n\u0131z. Jest&#8217;in <code>jest.mock()<\/code> fonksiyonu ile t\u00fcm mod\u00fclleri sahte versiyonlar\u0131yla de\u011fi\u015ftirebilir, <code>mockResolvedValue()<\/code> veya <code>mockRejectedValue()<\/code> ile belirli fonksiyonlar\u0131n d\u00f6nece\u011fi de\u011ferleri kontrol edebilirsiniz. Bu sayede testleriniz ger\u00e7ek servislere ba\u011f\u0131ml\u0131 olmaz, daha h\u0131zl\u0131 ve g\u00fcvenilir \u00e7al\u0131\u015f\u0131r.<\/p>\n<h4>Soru 3: Testlerimi ne s\u0131kl\u0131kla \u00e7al\u0131\u015ft\u0131rmal\u0131y\u0131m?<\/h4>\n<p><strong>Cevap:<\/strong> Birim testleri geli\u015ftirme s\u00fcrecinde m\u00fcmk\u00fcn oldu\u011funca s\u0131k, hatta her kod de\u011fi\u015fikli\u011finde veya kaydetti\u011finizde \u00e7al\u0131\u015ft\u0131r\u0131lmal\u0131d\u0131r (Jest&#8217;in <code>--watch<\/code> modu bunun i\u00e7in idealdir). Entegrasyon testleri ve u\u00e7tan uca testler ise daha \u00e7ok s\u00fcrekli entegrasyon (CI) boru hatt\u0131n\u0131n (pipeline) bir par\u00e7as\u0131 olarak, her kod birle\u015ftirmesinde veya da\u011f\u0131t\u0131mdan \u00f6nce otomatik olarak \u00e7al\u0131\u015ft\u0131r\u0131lmal\u0131d\u0131r. Bu, hatalar\u0131n erken a\u015famada tespit edilmesini sa\u011flar.<\/p>\n<h4>Soru 4: Ajan testlerinde performans nas\u0131l \u00f6l\u00e7\u00fcl\u00fcr?<\/h4>\n<p><strong>Cevap:<\/strong> Ajan testlerinde do\u011frudan performans \u00f6l\u00e7\u00fcm\u00fc (\u00f6rne\u011fin yan\u0131t s\u00fcresi) genellikle birim veya entegrasyon testlerinin birincil oda\u011f\u0131 de\u011fildir. Bu t\u00fcr \u00f6l\u00e7\u00fcmler daha \u00e7ok y\u00fck testleri (load testing) veya stres testleri (stress testing) ile yap\u0131l\u0131r. Ancak, testlerinizin kendisinin h\u0131zl\u0131 \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olmal\u0131s\u0131n\u0131z. Yava\u015f \u00e7al\u0131\u015fan testler geli\u015ftirme s\u00fcrecini aksat\u0131r. Jest, test s\u00fcrelerini raporlar ve bu sayede yava\u015f testleri tespit edip optimize edebilirsiniz. Ajan\u0131n ger\u00e7ek d\u00fcnyadaki performans\u0131n\u0131 \u00f6l\u00e7mek i\u00e7in ise Google Cloud Monitoring gibi ara\u00e7lar kullan\u0131lmal\u0131d\u0131r.<\/p>\n<h4>Soru 5: Test otomasyonunu CI\/CD s\u00fcre\u00e7lerine nas\u0131l entegre edebilirim?<\/h4>\n<p><strong>Cevap:<\/strong> Test otomasyonunu CI\/CD s\u00fcre\u00e7lerinize entegre etmek, kod kalitesini g\u00fcvence alt\u0131na alman\u0131n en etkili yoludur. Pop\u00fcler CI\/CD platformlar\u0131 (GitHub Actions, GitLab CI\/CD, Jenkins, Google Cloud Build) ile kolayca entegrasyon sa\u011flayabilirsiniz. Genellikle, her kod de\u011fi\u015fikli\u011fi bir depoya (repository) g\u00f6nderildi\u011finde, CI\/CD boru hatt\u0131 otomatik olarak tetiklenir. Bu boru hatt\u0131, projenizin ba\u011f\u0131ml\u0131l\u0131klar\u0131n\u0131 kurar, t\u00fcm testleri (birim, entegrasyon, E2E) \u00e7al\u0131\u015ft\u0131r\u0131r ve testler ba\u015far\u0131s\u0131z olursa da\u011f\u0131t\u0131m\u0131 durdurur. Testlerin ba\u015far\u0131l\u0131 olmas\u0131 durumunda ise kodun bir sonraki a\u015famaya (\u00f6rne\u011fin, test ortam\u0131na da\u011f\u0131t\u0131m) ge\u00e7mesine izin verir. Bu, s\u00fcrekli ve otomatik bir kalite kontrol d\u00f6ng\u00fcs\u00fc olu\u015fturur.<\/p>\n<p>#GoogleADK #TypeScript #AjanTesti #Yaz\u0131l\u0131mTesti #Jest #Mocking #EntegrasyonTesti #BirimTesti #Chatbot #YapayZeka<\/p>\n<div class=\"github-example-link\"><strong>\u00d6rnek kod:<\/strong> <a href=\"https:\/\/github.com\/fatihsoysalcom\/test-adk-agent-logic-with-mocks\" target=\"_blank\" rel=\"noopener noreferrer\">github.com\/fatihsoysalcom\/test-adk-agent-logic-with-mocks<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"Google ADK TypeScript ajanlar\u0131, kullan\u0131c\u0131larla etkile\u015fim kuran, belirli g\u00f6revleri otomatikle\u015ftiren veya karma\u015f\u0131k i\u015f mant\u0131\u011f\u0131n\u0131 y\u00fcr\u00fcten yaz\u0131l\u0131m bile\u015fenleridir.","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-44445","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi\" \/>\n<meta property=\"og:description\" content=\"Google ADK TypeScript ajanlar\u0131, kullan\u0131c\u0131larla etkile\u015fim kuran, belirli g\u00f6revleri otomatikle\u015ftiren veya karma\u015f\u0131k i\u015f mant\u0131\u011f\u0131n\u0131 y\u00fcr\u00fcten yaz\u0131l\u0131m bile\u015fenleridir.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-31T18:12:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-31T18:13:21+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"36 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi\",\"datePublished\":\"2026-08-31T18:12:49+00:00\",\"dateModified\":\"2026-08-31T18:13:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\"},\"wordCount\":4627,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\",\"name\":\"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-08-31T18:12:49+00:00\",\"dateModified\":\"2026-08-31T18:13:21+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/","og_locale":"tr_TR","og_type":"article","og_title":"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi","og_description":"Google ADK TypeScript ajanlar\u0131, kullan\u0131c\u0131larla etkile\u015fim kuran, belirli g\u00f6revleri otomatikle\u015ftiren veya karma\u015f\u0131k i\u015f mant\u0131\u011f\u0131n\u0131 y\u00fcr\u00fcten yaz\u0131l\u0131m bile\u015fenleridir.","og_url":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-08-31T18:12:49+00:00","article_modified_time":"2026-08-31T18:13:21+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"36 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi","datePublished":"2026-08-31T18:12:49+00:00","dateModified":"2026-08-31T18:13:21+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/"},"wordCount":4627,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/","url":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/","name":"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-08-31T18:12:49+00:00","dateModified":"2026-08-31T18:13:21+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/google-adk-typescript-ajanlarini-cumleleri-kovalamadan-test-etme-rehberi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Google ADK TypeScript Ajanlar\u0131n\u0131 C\u00fcmleleri Kovalamadan Test Etme Rehberi"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/44445","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=44445"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/44445\/revisions"}],"predecessor-version":[{"id":44446,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/44445\/revisions\/44446"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=44445"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=44445"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=44445"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}