Skip to content

Bölüm 8 / 12

Uçtan uca test

Playwright.

13 dakikalık okuma

Piramidin tepesine geldik. Birim ve entegrasyon testleri parçaları ve bağlantıları kanıtladı; ama "vatandaş tarayıcıyı açtı, formu doldurdu, başvurusunu gönderdi ve sonucu gördü" cümlesini yalnızca uçtan uca test kanıtlayabilir: gerçek tarayıcı, gerçek frontend, gerçek API, gerçek veritabanı — hepsi birlikte. Bu katmanın tarihi kararsız testlerle yazıldı; modern araç Playwright, o tarihin derslerini mimarisine gömdü: elemanı bekleyen locator'lar, kendiliğinden bekleyen eylemler, yeniden deneyen web-first assertion'lar. Bu derste Playwright'ı kurup ilk akış testini yazacak, kimlik durumunu storageState ile bir kez kurup her teste taşıyacak, kırılan testi trace viewer ile saniyeler içinde teşhis edecek ve E2E'nin en zor disiplinini öğreneceksin: az sayıda, bağımsız, kararlı test.

01Ne öğreneceksin

  • E2E'nin yeri: ne zaman değer üretir, ne zaman yük olur
  • Playwright mimarisi: üç tarayıcı motoru, koşucu, yapılandırma, webServer
  • Locator felsefesi: getByRole, tembel değerlendirme, auto-wait ve eylem ön koşulları
  • Web-first assertion: kendiliğinden yeniden deneyen doğrulama; waitForTimeout yasağı
  • storageState ile kimliği bir kez kurup tüm testlere taşımak
  • Trace viewer / UI mode ile kırılan testin teşhisi
  • Düzen: Page Object ve fixture dozu; paralel worker'lar ve test bağımsızlığı
  • Kararlılık disiplini ve CI'da koşum (18. hat köprüsü); Selenium karşılaştırması

02Tepenin ekonomisi

2. dersin tablosunu hatırla: E2E en yüksek güveni verir — ve en yavaş, en pahalı, en kırılgan katmandır. Hata lokalizasyonu da en zayıftır: kırmızı bir E2E "akış bozuk" der; frontend mi, API mi, veritabanı mı, test ortamı mı — söylemez. Bu ekonomiden iki kural çıkar:

  • Az ve öz: E2E'ye yalnız kritik kullanıcı yolculukları yazılır — başvuru yapma, sonuç görüntüleme, belge yükleme, giriş/çıkış. "Her doğrulama mesajının E2E'si" dondurma külahına giden yoldur; alan doğrulaması birimde, uç sözleşmesi entegrasyonda zaten kanıtlandı. Ölçü yine aynı: bir davranışı yakalayabilecek en ucuz katmanda test et; E2E, katmanların toplamının veremeyeceği tek şeyi — bütünün kullanıcı gözüyle çalıştığını — kanıtlasın.
  • Sıfır tolerans kararlılığa: E2E katmanında kararsız test normalleştiği an katman ölür — "bir daha koştur" kültürü gerçek kırmızıyı da örter (2. ders). Bu dersin araç seçiminden yazım kurallarına her parçası, bu tek düşmana karşı kurgulanmıştır.

Terminoloji notu: yazılıda karşına sistem testi (bütünün gereksinimlere karşı testi) ve kabul testi (müşterinin/işin "bu iş bitti mi" onayı, 5. dersteki çift döngünün dış halkası) çıkar; otomatik E2E, ikisinin de modern uygulama biçimidir — kullanıcı yolculuğunu gereksinim diliyle doğrular.

03Playwright: kurulum ve mimari

npm init playwright@latest      # koşucu + config + örnek test + tarayıcı indirme
npx playwright test             # tüm testler, başsız (headless)
npx playwright test --ui        # UI mode: izleyerek koştur
npx playwright show-report      # HTML rapor

Playwright üç tarayıcı motorunu tek API ile sürer: Chromium, Firefox, WebKit (Safari'nin motoru) — aynı test üçünde de koşar; yapılandırmadaki projects bölümü bunu yönetir. Sürüş, WebDriver gibi HTTP tabanlı bir aracı protokol yerine tarayıcıyla doğrudan, olay tabanlı bir kanaldan yapılır; "eleman hazır mı" bilgisi anlık aktığı için beklemeler isabetlidir. İşe yarayan iki yapılandırma parçası:

// playwright.config.ts
export default defineConfig({
  use: {
    baseURL: 'http://localhost:5000',
    trace: 'on-first-retry',            // kırılan testin filmi (06. bölüm)
  },
  webServer: {                          // testten önce uygulamayı Playwright başlatır
    command: 'dotnet run --project ../Basvuru.Api',
    url: 'http://localhost:5000',
    reuseExistingServer: !process.env.CI,
  },
});

webServer küçük ama kıymetli: "önce uygulamayı elle ayağa kaldır" adımını ortadan kaldırır — test koşusu tek komuta iner, CI'da da aynen çalışır.

04Locator felsefesi: kararlılığın mimarisi

Kararsız E2E'nin klasik iki nedeni vardı: eleman daha DOM'a gelmeden ona uzanmak ve kırılgan seçiciler (#app > div:nth-child(3) > span). Playwright ikisini de mimariyle çözer.

Locator tembeldir: page.getByRole('button', { name: 'Başvur' }) elemanı o anda aramaz; bir tarif tutar. Arama, eylem anında yapılır ve auto-wait devreye girer: Playwright eleman görünür, etkin, sabit (animasyonu bitmiş) ve tıklamayı gerçekten alabilir olana dek — zaman aşımına kadar — kendiliğinden bekler. "Elemanı bekle, sonra tıkla" diye iki adım yazdığın Selenium düzeninin tamamı, burada tek satırın içindedir.

Seçici öncelikleri 7. derstekiyle aynıdır ve bu bir tesadüf değildir — Testing Library'nin felsefesi buraya da taşındı: önce getByRole (erişilebilirlik ağacı; 8. hattaki semantik HTML yine kâr payı ödüyor), sonra getByLabel, getByPlaceholder, getByText; kaçınılmazsa getByTestId. CSS/XPath en son çaredir çünkü yapıya bağlanır — görsel refactor testi kırar.

Web-first assertion'lar üçüncü ayaktır: await expect(locator).toBeVisible(), toHaveText, toHaveURL gibi doğrulamalar tek seferlik bakmaz; beklenti sağlanana ya da zaman aşımına dek yeniden dener. Asenkron arayüzde "assert anında henüz gelmemişti" sınıfı kararsızlığı kökünden keser. Bu üçlünün doğal sonucu da dersin en sert kuralıdır: page.waitForTimeout(3000) yasak. Sabit uyku, yavaş günde yine kırılır, hızlı günde zaman çalar; her uyku bir "neyi beklediğimi bilmiyorum" itirafıdır. Neyi bekliyorsan onu bekle: locator, assertion ya da waitForURL.

05İlk akış testi

import { test, expect } from '@playwright/test';

test('vatandaş başvuru yapabilir', async ({ page }) => {
  await page.goto('/ilanlar');

  await page.getByRole('link', { name: 'Mühendis (MUH-2025)' }).click();
  await page.getByLabel('E-posta').fill('aday@ornek.gov.tr');
  await page.getByLabel('Doğum tarihi').fill('2001-03-15');
  await page.getByRole('button', { name: 'Başvur' }).click();

  await expect(page).toHaveURL(/basvuru-alindi/);
  await expect(page.getByRole('heading', { name: /başvurunuz alındı/i })).toBeVisible();
  await expect(page.getByText(/başvuru numaranız/i)).toBeVisible();
});

test('boş formda alan hataları görünür', async ({ page }) => {   // negatif yol (2. ders)
  await page.goto('/ilanlar/muh-2025/basvur');
  await page.getByRole('button', { name: 'Başvur' }).click();

  await expect(page.getByText('E-posta zorunludur')).toBeVisible();
});

Dikkat çekenler: tek bir await ...click() satırında gezinme + bekleme + eylem birleşik; assertion'lar sonucu kullanıcı diliyle doğruluyor (URL, başlık, görünen metin); ve iki test birbirinden tamamen bağımsız — her biri kendi sayfasına kendisi gidiyor. Her test() taze bir tarayıcı bağlamı (context) alır: çerezler, localStorage, oturum — hepsi sıfırdan; izolasyonun tarayıcı katmanındaki karşılığı budur (3. dersteki "her teste yeni sınıf örneği"nin birebir dengi).

06Kimlik: storageState ile bir kez gir

Testlerin çoğu giriş yapılmış kullanıcı ister; her testin form üzerinden giriş yapması hem yavaştır hem giriş sayfasını tek hata noktası yapar (giriş bozulursa tüm paket kırmızı — teşhis gücü sıfır). Playwright deseni: girişi bir kez, ayrı bir kurulum projesinde yap; oturumu (çerez + localStorage) storageState dosyasına kaydet; tüm testler o dosyayla, hazır oturumla başlasın:

// auth.setup.ts
setup('giriş yap', async ({ page }) => {
  await page.goto('/giris');
  await page.getByLabel('E-posta').fill(process.env.TEST_KULLANICI!);
  await page.getByLabel('Parola').fill(process.env.TEST_PAROLA!);   // sır koda gömülmez (13-10)
  await page.getByRole('button', { name: 'Giriş' }).click();
  await expect(page.getByRole('link', { name: 'Başvurularım' })).toBeVisible();
  await page.context().storageState({ path: '.auth/aday.json' });
});

// config: setup projesi + ona bağımlı test projesi
projects: [
  { name: 'setup', testMatch: /auth\.setup\.ts/ },
  { name: 'chromium', use: { storageState: '.auth/aday.json' }, dependencies: ['setup'] },
]

Giriş akışının kendisi elbette test edilir — ama bir kez, kendi testinde; diğer yüz test onu tekrar etmez. Farklı roller için (aday ↔ denetçi) ayrı state dosyaları tutulur; 6. dersteki 403/IDOR senaryolarının E2E karşılığı, iki farklı state ile aynı sayfaya gitmektir. .auth/ klasörü depoya girmez (13-10: oturum da sırdır).

07Teşhis: trace viewer ve UI mode

E2E'nin teşhis zafiyetine Playwright'ın cevabı, koşunun filmini kaydetmektir. trace: 'on-first-retry' ayarıyla, kırılıp yeniden denenen her test için bir trace dosyası düşer; npx playwright show-trace onu açar: zaman çizelgesinde her adımın ekran görüntüsü, o andaki DOM anlık kopyası (üzerinde locator deneyebilirsin), ağ istekleri, konsol logları. "CI'da kırıldı, bende geçiyor" vakasının klasik çözümsüzlüğü — yeniden üretememek — burada ortadan kalkar: kırılan koşunun kendisi elindedir. CI, trace ve raporu artifact olarak saklar (18. hatta bağlanacak).

Geliştirme sırasındaki araç ise UI mode'dur (--ui): testleri izleyerek koşturur, her adımda durup DOM'a bakarsın; --debug aynı işi adım adım yürütmeyle yapar. Bir de tersi var: npx playwright codegen tıklamalarını koda çevirir — başlangıç için iskele çıkarır, ama ürettiği seçiciler her zaman 04. bölümün süzgecinden geçirilir; kayıt aracı mühendisliğin yerini tutmaz.

08Düzen: Page Object, fixture, paralellik

Testler çoğaldıkça aynı sayfa etkileşimleri tekrar eder; klasik çözüm Page Object desenidir — sayfanın locator'ları ve eylemleri bir sınıfta toplanır:

export class BasvuruSayfasi {
  constructor(private page: Page) {}
  eposta = () => this.page.getByLabel('E-posta');
  basvur = () => this.page.getByRole('button', { name: 'Başvur' });

  async doldurVeGonder(eposta: string) {
    await this.eposta().fill(eposta);
    await this.basvur().click();
  }
}

Doz uyarısı: Page Object bir soyutlama vergisidir — locator değişince tek yerde düzeltirsin (kazanç), ama testin ne yaptığı bir dolaylama arkasına saklanır (bedel). Küçük paketlerde çıplak locator'lar gayet meşrudur; desen, tekrar gerçekten ağrıtınca gelir (Hat 4'ün YAGNI'si). Playwright'ın test.extend fixture'ları da aynı işi kompozisyonla yapar: hazır sayfa nesneleri, hazır test verisi, hazır oturum — xUnit fixture kavramının (3. ders) buradaki karşılığı.

Paralellik: Playwright test dosyalarını ayrı worker süreçlerinde paralel koşturur. Bunun tek ön şartı 05. bölümde gördüğün bağımsızlıktır: her test kendi verisini kurar, ortak kayda yaslanmaz — aksi hâlde 6. dersteki izolasyon sorunları tarayıcı ölçeğinde geri gelir. test.describe.configure({ mode: 'serial' }) diye bir acil çıkış vardır ve kötü kokudur: testleri sıraya bağlamak, birinin kırılmasının diğerlerini anlamsızlaştırması demektir. Retry politikası da aynı dozla kullanılır: CI'da retries: 1-2 ağ türbülansına karşı makul bir amortisördür, ama retry ile geçen test bir borçtur — trace'i incelenir, nedeni kapatılır; "retry var nasılsa" kültürü kararsızlığı normalleştirir.

09Selenium'a kıyasla — ve CI penceresi

Selenium WebDriverPlaywright
SürüşW3C WebDriver protokolü; tarayıcı başına ayrı sürücü (chromedriver, geckodriver)Doğrudan, olay tabanlı kanal; sürücü kurulumu yok, motorları kendisi indirir
BeklemeVarsayılan yok; explicit/implicit wait'i sen kurarsın — tarihsel kararsızlığın ana kaynağıAuto-wait + web-first assertion mimaride
Araç setiÇekirdek kütüphane; koşucu, rapor, paralellik ayrı parçalardan derlenirKoşucu, trace, rapor, paralellik tek pakette
Dil/ekosistemÇok geniş dil desteği; devasa kurulu taban, mevcut kurumsal paketlerde hâlâ standartTS/JS birinci sınıf (.NET/Java/Python bağları da var); yeni projelerin fiilî tercihi

Dürüst özet: Selenium'un tarihsel değeri ve kurulu tabanı büyüktür; mülakatta "Selenium?" sorusuna doğru cevap, kavramların ortak olduğunu (seçici, bekleme, sayfa nesnesi) ve farkın beklemenin kimin sorumluluğu olduğunda yattığını söylemektir. CI tarafına şimdilik bir pencere: E2E paketi, dağıtım hattında entegrasyon testlerinden sonra, tercihen dağıtım sonrası bir duman (smoke) koşusu olarak da koşar; tarayıcılı koşu için hazır konteyner imajları kullanılır, trace/rapor artifact olarak saklanır — mekanizması 18. hattın işi.

10Mini alıştırma — ilk akışın filmi

Yaklaşık 20 dakika · npm + herhangi bir web projen (yoksa bu site!)

  1. Kur. npm init playwright@latest; config'e baseURL yaz. Test hedefi olarak kendi projenin bir akışını seç — elinde yoksa bu çalışma sitesini kullan: "ana haritadan bir hatta gir, ilk dersi aç, ders kutusundan tamamlandı işaretle".
  2. Akışı yaz. Testi yalnız getByRole/getByText locator'larıyla yaz; sonucu URL + görünen metinle doğrula. CSS seçici kullanmadan bitirebildin mi? Kullanmak zorunda kaldığın yer, sayfanın semantik eksiğidir — not et.
  3. Negatif yol. Bir de olmaması gerekeni doğrula: var olmayan bir sayfaya gidince 404 içeriği, ya da boş form gönderiminde hata metni.
  4. Filmi izle. Testi bilerek kır (yanlış metin bekle), --trace on ile koştur ve show-trace ile aç: kırılma anındaki DOM'da doğru locator'ı trace içinden bul. Teşhisin kaç saniye sürdüğünü gör.
  5. Uyku provası. Teste waitForTimeout(3000) ekle, koşu süresine etkisine bak, sonra sil ve yerine neyi beklediğini söyleyen bir assertion koy. Farkı bir cümleyle yaz: sabit süre ↔ koşul bekleme.
  6. Paralellik denemesi. Testi ikinci bir dosyaya kopyala (farklı senaryoyla), koşunun iki worker'da paralel gittiğini raporda gör. İki test ortak bir duruma yazsaydı ne olurdu — 6. dersteki cevabı buraya bağla.

11Kendini sına

E2E test ne zaman değer üretir, ne zaman yüktür? "Az sayıda E2E" kuralının gerekçesini katman ekonomisiyle açıkla.

E2E, sistemi kullanıcının gördüğü yerden — gerçek tarayıcı, gerçek frontend, gerçek API ve veritabanıyla — sürer ve tek benzersiz kanıtı verir: bütün, kullanıcı gözüyle çalışıyor. Bedeli katman ekonomisinin en pahalı ucudur: en yavaş koşu, en yüksek yazım/bakım maliyeti, en kırılgan altyapı ve en zayıf hata lokalizasyonu — kırmızı E2E "akış bozuk" der ama frontend mi, API mi, ortam mı söylemez; teşhis bir seans ister. Bu yüzden değer ürettiği yer, az sayıda kritik kullanıcı yolculuğudur: başvuru yapma, giriş, sonuç görüntüleme gibi bozulması en pahalı akışlar ve dağıtım sonrası duman koşusu. Yüke dönüştüğü yer, alt katmanların işini üstlenmesidir: her alan doğrulamasının, her uç sözleşmesinin E2E ile test edilmesi dondurma külahı üretir — saatler süren, sürekli kırılan, kimsenin bakmadığı koşular. Kural: her davranış onu yakalayabilecek en ucuz katmanda test edilir; E2E yalnız katmanların toplamının veremeyeceğini kanıtlar. İkinci şart kararlılıktır: bu katmanda kararsız test normalleşirse "bir daha koştur" kültürü gerçek hatayı da örter; retry ile geçen her test incelenmesi gereken bir borçtur.

Playwright'ta locator, auto-wait ve web-first assertion nasıl birlikte çalışır? waitForTimeout neden yasaktır?

Locator tembel bir tariftir: getByRole('button', { name: 'Başvur' }) yazıldığı anda DOM'da arama yapmaz; eylem anında değerlendirilir. O anda auto-wait devreye girer: Playwright, eleman görünür, etkin, sabit (animasyon bitmiş) ve etkileşimi gerçekten alabilir olana dek zaman aşımı sınırında kendiliğinden bekler — "önce bekle sonra tıkla" ritüeli tek satıra gömülüdür. Web-first assertion'lar (await expect(locator).toBeVisible(), toHaveText, toHaveURL) tek seferlik bakmaz; beklenti sağlanana dek yeniden dener — asenkron arayüzde "assert anında henüz gelmemişti" kararsızlığını kökünden keser. Seçici önceliği Testing Library ile aynıdır: önce rol + erişilebilir isim, sonra etiket/metin; CSS/XPath yapıya bağlandığı için son çaredir. waitForTimeout yasaktır çünkü sabit uyku iki yönde de yanlıştır: yavaş günde yine kırılır (kararsızlık çözülmez), hızlı günde koşuyu boşuna bekletir; ayrıca her uyku "neyi beklediğimi bilmiyorum" itirafıdır ve gerçek nedeni maskeleyerek borcu büyütür. Doğrusu, beklenen koşulun kendisini beklemektir: locator eylemi, assertion ya da waitForURL. Kararlılığın mimariye gömülmesi, Playwright'ı bekleme sorumluluğunu geliştiriciye bırakan WebDriver düzeninden ayıran ana çizgidir.

storageState deseni nasıl çalışır ve neden her testte form üzerinden giriş yapılmaz? Farklı roller ve güvenlik senaryoları E2E'de nasıl kurulur?

Desen: giriş, ayrı bir kurulum (setup) projesinde bir kez form üzerinden yapılır; başarı doğrulanır ve oturumun tarayıcı durumu — çerezler + localStorage — context().storageState({ path }) ile bir dosyaya kaydedilir; asıl test projesi config'te bu dosyayı storageState olarak kullanır ve dependencies: ['setup'] ile kurulumdan sonra koşar — her test hazır oturumla başlar. Her testte giriş yapmamanın iki nedeni var: hız (giriş akışı yüz kez tekrar eder) ve teşhis gücü (giriş sayfası bozulduğunda tüm paket kırmızıya boyanır — tek hata yüz kırmızı üretir, neden görünmez). Girişin kendisi elbette test edilir, ama bir kez, kendi testinde. Farklı roller için ayrı state dosyaları tutulur (aday.json, denetci.json); yetki senaryolarının E2E karşılığı iki farklı state ile aynı sayfaya gitmektir — adayın görmemesi gereken yönetim bağlantısının yokluğu queryBy mantığıyla, yetkisiz sayfanın engellendiği görünür davranışla doğrulanır (asıl 401/403/IDOR yükü daha ucuz katmanda, entegrasyon testindedir). Güvenlik hijyeni: test kimlik bilgileri ortam değişkeninden gelir, state dosyaları depoya girmez — oturum da bir sırdır.

Trace viewer neyi çözer? Page Object'in dozu nedir ve Playwright ile Selenium arasındaki temel farkları nasıl özetlersin?

Trace viewer, E2E'nin en zayıf yanını — teşhisi — çözer: trace: 'on-first-retry' ile kırılan koşunun filmi kaydedilir; zaman çizelgesinde her adımın ekran görüntüsü, o anki DOM anlık kopyası (üzerinde locator bile denenir), ağ istekleri ve konsol logları vardır. "CI'da kırılıyor, bende geçiyor" vakasının çözümsüzlüğü yeniden üretememekti; trace ile kırılan koşunun kendisi elindedir, CI bunu artifact olarak saklar. Geliştirmede UI mode (--ui) adım adım izleme sağlar; codegen iskele çıkarır ama ürettiği seçiciler locator süzgecinden geçirilir. Page Object, sayfa etkileşimlerini tek sınıfta toplar: locator değişince tek yer düzelir — ama testin ne yaptığını dolaylamanın arkasına saklar; küçük pakette çıplak locator meşrudur, desen tekrar gerçekten ağrıtınca gelir (YAGNI). Playwright'ın test.extend fixture'ları aynı ihtiyacı kompozisyonla karşılar. Selenium karşılaştırması üç cümledir: Selenium W3C WebDriver protokolü ve tarayıcı başına ayrı sürücüyle çalışır, bekleme sorumluluğu geliştiricidedir (tarihsel kararsızlığın kaynağı) ve çekirdek kütüphanedir — koşucu/rapor ayrı derlenir; Playwright doğrudan olay tabanlı kanalla sürer, auto-wait + web-first assertion mimaridedir ve koşucu-trace-paralellik tek pakettir. Kavramlar (seçici, bekleme, sayfa nesnesi) ortaktır; fark, beklemenin kimin sorumluluğu olduğudur.

12Sınav köşesi

Yazılıda nasıl sorulur

(1) Uçtan uca (E2E) test nedir? (2) Sistem testi ve kabul testi nedir, farkları nelerdir? (3) E2E testler neden az sayıda tutulmalıdır? (4) Playwright nedir, hangi tarayıcıları destekler? (5) Selenium ile Playwright arasındaki farklar nelerdir? (6) Test otomasyonunda bekleme (wait) stratejileri nelerdir? (7) Page Object deseni nedir? (8) Kararsız (flaky) E2E testlerinin nedenleri ve çözümleri nelerdir? (9) E2E testlerde oturum/kimlik yönetimi nasıl yapılır? (10) Duman (smoke) testi nedir?

Sözlüde nasıl anlatılır — 2 dakikalık taslak

Düzen: (1) Yer — "E2E'yi piramidin tepesinde, az sayıda kritik kullanıcı yolculuğu için kullanırım: başvuru, giriş, sonuç. Alan doğrulaması birimde, uç sözleşmesi entegrasyonda zaten kanıtlı — E2E yalnız bütünün çalıştığını kanıtlar." (2) Araç — "Playwright kullanırım: üç motoru tek API ile sürer, locator'ları tembeldir ve auto-wait ile eylem anında bekler; assertion'ları web-first'tür, beklenti sağlanana dek yeniden dener. Bu yüzden pakette tek bir waitForTimeout yoktur — sabit uyku, neyi beklediğini bilmemektir." (3) Seçici — "Elemanları getByRole ile erişilebilirlik ağacından bulurum; CSS/XPath yapıya bağlanır, görsel refactor'da kırılır." (4) Operasyon — "Girişi setup projesinde bir kez yapar, storageState ile tüm testlere taşırım; testler bağımsızdır, worker'larda paralel koşar. Kırılan testin trace'ini açarım: adım adım ekran, DOM, ağ — 'bende geçiyor' tartışması biter." (5) Kıdem vuruşu — "Bu katmanda kararsızlığa sıfır tolerans uygularım: retry ile geçen test kapatılmış değil ertelenmiş bir borçtur, trace'ini inceler nedenini kapatırım. Selenium sorulursa kavramların ortak olduğunu, farkın beklemenin kimin sorumluluğunda olduğu söylerim."