Skip to content

Bölüm 7 / 12

Frontend testi

Jasmine/Karma (Angular), Jest + Testing Library (React).

14 dakikalık okuma

Şimdiye kadarki test bilgin sunucu tarafındaydı; oysa 10. ve 11. hatlarda yazdığın Angular ve React kodu da mantık taşıyor — form doğrulama, durum geçişleri, koşullu görünürlük — ve o mantık da kırılıyor. Frontend testinin zorluğu araç değil hedef seçimidir: bileşenin iç durumunu mu test edeceksin, kullanıcının gördüğünü mü? Bu ders iki ekosistemi de kurar: Angular tarafında Jasmine + TestBed (ve Karma'nın emekliliğinin hikâyesi), HttpTestingController, fakeAsync; React tarafında Jest + Testing Library felsefesi — "kullanıcı gibi sorgula" — user-event ve ağ sınırını kesen MSW. Kapanışta iki kıdem konusu var: 12. hattan devrettiğimiz senet olan Jest'in modül önbelleği ve test izolasyonu, ve snapshot testinin neden çoğu ekipte değersizleştiği.

01Ne öğreneceksin

  • Frontend testinin hedef sorusu: iç durum değil, kullanıcının gördüğü
  • Jasmine sözdizimi; Karma'nın kullanımdan kaldırılışı ve güncel koşucular
  • TestBed / ComponentFixture: Angular bileşen ve servis testi, detectChanges
  • HttpTestingController ile HTTP sınırı; fakeAsync/tick
  • Testing Library felsefesi: getByRole öncelik sırası, erişilebilirlik bağı
  • user-event ile gerçekçi etkileşim; findBy/waitFor
  • MSW: ağı bileşen kodunu değiştirmeden kesmek
  • Jest modül sistemi: jest.mock hoisting, modül önbelleği × izolasyon (12-03 senedi)
  • Snapshot testinin doğru dozu ve çürüme mekanizması

02Hedef sorusu: neyi test ediyorsun?

Bir arayüz bileşeninin iki yüzü vardır: içeride durum ve metotlar, dışarıda kullanıcının gördüğü ve dokunduğu DOM. Frontend test tarihinin en büyük ders değişimi şu cümlede özetlenir: testin, kullanıcının göremeyeceği hiçbir şeye bağlanmasın. Bileşenin iç alanını (component.acikMi = true) okuyan test, 1. dersteki kırılgan test tanımının frontend hâlidir: refactor'da kırılır, gerçek hatayı (alan doğru ama ekran yanlış) kaçırır. Doğru hedef, davranışın kullanıcı tarafı: "butona basılınca listede üç satır görünür", "boş e-postayla gönderilince hata metni çıkar".

İkinci ayrım koşu ortamıdır: birim/bileşen testleri ya jsdom gibi Node içinde çalışan bir DOM taklidinde ya da gerçek tarayıcıda koşar. jsdom hızlıdır ama taklittir — gerçek yerleşim (layout), gerçek CSS, gerçek odak davranışı yoktur; "ekranda gerçekten görünüyor mu" sorusunun nihai cevabı 8. dersin (E2E) işidir. Piramit burada da geçerli: bileşen mantığı bu derste, gerçek tarayıcıda tam akış tepede, az sayıda.

03Angular: Jasmine — ve Karma'nın emekliliği

Angular CLI'nin yıllardır ürettiği ikili: test çerçevesi Jasmine (testin yazıldığı API) + koşucu Karma (testleri gerçek tarayıcıda koşturan sunucu). Jasmine sözdizimi, xUnit kavramlarının JS karşılığıdır — 3. dersteki her kavramı eşleyebilirsin:

describe('UcretHesaplayici', () => {          // test sınıfı karşılığı: grup
  let hesap: UcretHesaplayici;

  beforeEach(() => {                           // ctor karşılığı: her testten önce
    hesap = new UcretHesaplayici();
  });

  it('25 yaş altına yarım ücret uygular', () => {   // [Fact] karşılığı
    expect(hesap.hesapla(22)).toBe(125);
  });

  it('geçersiz yaşta hata fırlatır', () => {
    expect(() => hesap.hesapla(-1)).toThrowError(/yaş/i);
  });
});

toBe referans/ilkel eşitliği, toEqual derin yapısal eşitlik (xUnit'teki Equivalent ruhu); spy'lar için spyOn(nesne, 'metot') ve jasmine.createSpyObj var — Moq'un görevini burada çerçevenin kendisi görür.

Karma'nın durumu, güncel bilgi sorusu olarak bilinmeye değer: Karma ekibi projeyi 2023'te resmî olarak kullanımdan kaldırdı (deprecated); Angular ekibi de CLI için yeni koşuculara yöneldi — önce deneysel Jest ve Web Test Runner desteği, ardından yeni nesil CLI test altyapısında Vitest'in öne çıkışı. Pratik sonuç: mevcut projelerde Karma hâlâ karşına çıkar (bu yüzden tanıman gerekir: tarayıcı açar, dosya izler, ng test ile koşar), ama yeni projede koşucu seçimi artık bilinçli bir karardır. Neyse ki asıl bilgin koşucudan bağımsız: Jasmine sözdizimi ve TestBed API'si, koşucu değişse de aynı kalır — yatırımını oraya yap.

04Angular: TestBed ve ComponentFixture

TestBed, testin içinde küçük bir Angular ortamı kurar: bileşeni derler, DI konteynerini çalıştırır (10. hattaki inject düzeni aynen işler), sana iki kulplu bir ComponentFixture verir: componentInstance (sınıf) ve nativeElement (DOM):

describe('BasvuruFormuComponent', () => {
  let fixture: ComponentFixture<BasvuruFormuComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [BasvuruFormuComponent],        // standalone bileşen doğrudan import edilir
      providers: [
        { provide: BasvuruServisi, useValue: sahteServis },  // DI: sınırı değiştir (15-06 deseni)
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(BasvuruFormuComponent);
    fixture.detectChanges();                   // ilk değişiklik algılama = ilk çizim
  });

  it('kontenjan doluysa gönder butonunu kilitler', () => {
    sahteServis.kontenjan.set(0);
    fixture.detectChanges();                   // durum değişti → yeniden çiz

    const buton = fixture.nativeElement.querySelector('button[type="submit"]');
    expect(buton.disabled).toBeTrue();
  });
});

İki kritik ayrıntı: (1) detectChanges sende — testte değişiklik algılamayı çerçeve değil sen tetiklersin; durumu değiştirip DOM'a bakmadan önce çağırmayı unutmak, bu ekosistemin bir numaralı "testim neden eskiyi görüyor" hatasıdır (signal tabanlı bileşenlerde ve zoneless kurulumda da kalıp aynıdır: değiştir, algılat, doğrula). (2) Doğrulamayı DOM üzerinden yap — component.kilitliMi alanını değil butonun gerçek disabled durumunu assert et; 02. bölümün ilkesi burada ete kemiğe bürünür. Servis testi daha da yalındır: bileşen yoksa fixture da gerekmez, TestBed.configureTestingModule({ providers: [...] }) + TestBed.inject(Servis) yeter.

05Angular: HTTP sınırı ve zaman

HTTP çağrısı yapan servisin testi için Angular'ın hazır çözümü vardır — 15-06'daki "sınırı değiştir, kalanı gerçek bırak" ilkesinin çerçeve içi hâli. provideHttpClientTesting(), gerçek arka ucu HttpTestingController ile değiştirir: istekler kuyruğa girer, sen teker teker karşılarsın:

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [provideHttpClient(), provideHttpClientTesting(), IlanServisi],
  });
  servis = TestBed.inject(IlanServisi);
  httpMock = TestBed.inject(HttpTestingController);
});

afterEach(() => httpMock.verify());            // karşılanmamış istek kaldıysa test kırılır

it('ilanları getirir', () => {
  let sonuc: Ilan[] = [];
  servis.getir().subscribe(i => (sonuc = i));

  const istek = httpMock.expectOne('/api/ilanlar');   // tam bir istek bekleniyor
  expect(istek.request.method).toBe('GET');
  istek.flush([{ id: 1, ad: 'Mühendis' }]);           // cevabı test verir

  expect(sonuc.length).toBe(1);
});

verify()'ı afterEach'e koymak küçük görünen büyük bir disiplindir: beklemediğin bir isteğin sessizce gitmesini (ya da beklediğinin hiç gitmemesini) her testte yakalar. Zaman tarafında Angular'ın aracı fakeAsync'tir — 4. dersteki FakeTimeProvider'ın birebir ruh ikizi: test gövdesi sahte bir zaman bölgesinde koşar, tick(300) sanal zamanı 300 ms ilerletir (debounceTime(300)'lü arama kutusunu beklemeden test edersin), flush() bekleyen tüm zamanlayıcıları boşaltır. Gerçek setTimeout bekleyen test, 2. dersin kararsız test tanımına girer.

06React: Testing Library felsefesi

React tarafının yaygın ikilisi: koşucu + çerçeve olarak Jest (ya da aynı API'yle Vitest), bileşen sorgulama katmanı olarak React Testing Library (RTL). RTL'in kurucu cümlesi bu dersin 02. bölümünü doktrine çevirir: "Testlerin, yazılımının kullanılma biçimine ne kadar benzerse o kadar güven verir." Somut karşılığı sorgu öncelik sırasıdır — DOM'u kullanıcının bulduğu gibi bul:

ÖncelikSorguNeden
1getByRole('button', { name: /gönder/i }) Erişilebilirlik ağacından bulur — ekran okuyucunun gördüğünü görürsün; rol + erişilebilir isim, 8-05'teki (web-html-semantik) yatırımın karşılığıdır
2getByLabelText('E-posta') Form alanını etiketiyle — label bağını da bedavaya doğrular
3getByText, getByPlaceholderText Görünen metin; kullanıcının okuduğu şey
son çaregetByTestId('basvuru-satiri') Kullanıcı test-id göremez; ancak rol/metin ile bulunamayan yapılar için
test('boş e-postayla gönderilince hata gösterir', async () => {
  const user = userEvent.setup();
  render(<BasvuruFormu />);

  await user.click(screen.getByRole('button', { name: /başvur/i }));

  expect(await screen.findByText(/e-posta zorunludur/i)).toBeInTheDocument();
});

Üç teknik nokta: user-event, ham fireEvent'in aksine gerçek kullanıcı dizisini üretir (odak, keydown/keyup, input) — "programatik olarak olur ama kullanıcı yapamaz" sınıfı hataları yakalar; API'si async'tir, await unutulmaz (3. dersteki await tuzağının JS kardeşi). findBy* = getBy* + bekleme: sonuç asenkron geliyorsa (state güncellemesi, ağ) findBy ya da waitFor kullanılır; getBy anında arar ve bulamazsa patlar. Yokluğu doğrulamak içinse queryBy* — bulamayınca hata yerine null döner: expect(screen.queryByText(/hata/i)).not.toBeInTheDocument().

07Ağ sınırı: MSW

Bileşen veri çekiyorsa iki kötü seçenek vardır: gerçek API'ye gitmek (kararsız, yavaş) ya da fetch/axios'u fonksiyon olarak mock'lamak — bu ikincisi 4. dersin "sahip olmadığın türü mock'lama" ihlalidir ve bileşenin veri çekme biçimine bağlanır (axios'tan fetch'e geçen refactor tüm testleri kırar). Modern çözüm MSW (Mock Service Worker): ağı istek seviyesinde keser — bileşen gerçekten HTTP isteği atar, MSW cevabı verir; bileşen kodu ve veri katmanı hiç değişmez:

const server = setupServer(
  http.get('/api/ilanlar', () =>
    HttpResponse.json([{ id: 1, ad: 'Mühendis' }])),
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());       // testin eklediği handler'lar sıfırlanır
afterAll(() => server.close());

test('hata durumunda yeniden dene butonu çıkar', async () => {
  server.use(http.get('/api/ilanlar', () => HttpResponse.error()));  // bu teste özel senaryo

  render(<IlanListesi />);

  expect(await screen.findByRole('button', { name: /yeniden dene/i })).toBeInTheDocument();
});

Desene dikkat: varsayılan mutlu yol handler'ları bir kez kurulur; her test kendi senaryosunu server.use ile üstüne yazar, resetHandlers izolasyonu korur — 15-06'daki "her test kendi verisini kurar" kuralının ağ hâli. MSW'nin HttpTestingController'dan farkı da felsefidir: Angular aracı istekleri senin karşılamanı bekler (beklenmedik istek = hata), MSW bir sahte sunucu gibi davranır; ikisi de meşrudur, ikisinde de negatif senaryolar (500, zaman aşımı, boş liste) mutlu yol kadar test edilir — 2. dersin disiplini.

08Jest'in modül sistemi: hoisting ve önbellek

12-03'te Node'un require önbelleğini görmüştün: bir modül ilk import'ta çalışır, sonrakiler önbellekten gelir — modül seviyesindeki her değişken fiilen bir singleton'dır. Şimdi senet ödeme zamanı, çünkü bu gerçek testte iki yerden ısırır:

Birincisi, jest.mock'un çalışma biçimi. Şu kod sana sıralı görünür ama değildir:

import { ucretGetir } from './ucretServisi';
jest.mock('./ucretServisi');                   // Jest bunu dosyanın EN BAŞINA taşır (hoisting)

// factory'li biçimde dış değişkene erişim tuzağı:
const sahteCevap = { ucret: 250 };
jest.mock('./ucretServisi', () => ({
  ucretGetir: () => sahteCevap,               // HATA: factory, sahteCevap tanımlanmadan koşar
}));

Jest, jest.mock çağrılarını derleme adımında dosyanın tepesine kaldırır ki import edilen modül daha yüklenirken sahtesi geçsin. Bedeli: mock factory, dışarıdaki değişkenlere erişemez (henüz tanımlı değiller) — Jest yalnızca mock önekiyle başlayan isimlere (const mockCevap = ...) bilerek izin verir. Bu kuralı bilmeyen, "değişkenim neden undefined" hatasıyla saatler kaybeder.

İkincisi, modül önbelleği × test izolasyonu. Modülün tepesindeki durum, aynı test dosyasının testleri arasında paylaşılır:

// sayac.js
let sayi = 0;                                  // modül seviyesinde durum = singleton
export const artir = () => ++sayi;

// testte: ikinci test birinciden kirli başlar → sıra bağımlılığı (2. dersin flaky kaynağı)
// çözüm: modülü önbellekten düşürüp taze kopya almak
beforeEach(() => jest.resetModules());
test('taze modülle', async () => {
  const { artir } = await import('./sayac');   // resetModules sonrası: yeni örnek
  expect(artir()).toBe(1);
});

jest.resetModules() modül kayıt defterini boşaltır; jest.isolateModules(fn) aynı işi tek blok için yapar. Jest'in dosyalar arası izolasyonu zaten vardır (her test dosyası ayrı modül kaydıyla, ayrı worker'da koşar) — sorun hep dosya içi paylaşımdadır. Üç ayar da karıştırılır, ayır: clearMocks çağrı kayıtlarını siler, resetMocks implementasyonları da sıfırlar, restoreMocks spyOn ile sarılan orijinalleri geri koyar — yapılandırmada üçünü açmak (clearMocks: true asgari) testler arası sızıntının standart sigortasıdır. Kalıcı ders, 3. dersteki statik alan uyarısıyla aynıdır: izolasyonu bozan her zaman paylaşılan durumdur; frontend'de o durum çoğu kez modülün tepesinde yaşar.

09Snapshot testi: dozu ve çürümesi

Jest'in snapshot testi, bir değerin (çoğu kez render edilmiş DOM'un) serileştirilmiş hâlini ilk koşuda dosyaya kaydeder, sonraki koşularda karşılaştırır: expect(agac).toMatchSnapshot(). Cazibesi bedavalığıdır — tek satırla "her şey aynı kaldı" güvencesi. Çürüme mekanizması da tam oradadır: dev bir DOM snapshot'ı hangi davranışın beklendiğini söylemez; kırıldığında geliştirici 300 satırlık diff'i okumak yerine jest -u ile günceller — okunmadan onaylanan snapshot, assert'süz testtir (1. dersteki kapsama tiyatrosunun kardeşi). Kırmızısı bilgi taşımayan test, ekipçe görmezden gelinmeye mahkûmdur.

Doğru doz: snapshot'ı küçük, odaklı ve okunur tut — toMatchInlineSnapshot() beklentiyi test dosyasının içine yazar, code review'da diff olarak okunur; iyi adaylar bir hata mesajının metni, bir serileştiricinin çıktısı, bir config üretiminin sonucudur. Bileşen davranışı içinse sorgular (06. bölüm) her zaman daha iyi testtir: "buton kilitli" iddiası, 40 satır DOM ağacından daha dayanıklı ve daha konuşkandır.

10Mini alıştırma — iki dünyada aynı bileşen

Yaklaşık 20 dakika · 10. ya da 11. hattaki projen (hangisi eldeyse)

  1. Hedef seç. Formlu bir bileşenini al (yoksa: e-posta + gönder butonundan oluşan mini başvuru formu yaz). Davranış listesi çıkar: boş gönderim hata gösterir, geçerli gönderim servisi çağırır, beklerken buton kilitlenir.
  2. Kullanıcı gözü testi. (React) RTL ile üç davranışı getByRole / findByText sorgularıyla test et; getByTestId'yi yalnız gerçekten gerekirse kullan. (Angular) Aynı üçlüyü TestBed ile yaz; assert'leri componentInstance alanlarına değil nativeElement DOM'una yap ve her durum değişiminden sonra detectChanges çağır.
  3. Ağ senaryosu. Servis çağrısını MSW (React) ya da HttpTestingController (Angular) ile karşıla; bir mutlu yol + bir 500 senaryosu yaz. 500'de kullanıcının ne gördüğünü assert et — boş ekran da bir hatadır.
  4. İzolasyon deneyi. Modül seviyesinde durum tutan küçük bir modül yaz (sayaç); iki testin birbirini kirlettiğini gör, jest.resetModules + dinamik import ile düzelt. 12-03'teki önbellek bilgisiyle bağını bir cümleyle not et.
  5. Kırılganlık testi. Bileşende görsel bir refactor yap (sarmalayıcı div ekle, sınıf adı değiştir — davranış aynı). Hangi testlerin kırıldı? Sorgu tabanlı testler ayakta kalmalı; kırılan varsa iç yapıya bağlanmışsın demektir.

11Kendini sına

Frontend testinde "kullanıcının gördüğünü test et" ilkesi ne demektir? Testing Library'nin sorgu öncelik sırası bu ilkeyi nasıl uygular?

Bir bileşenin iç durumu (alanlar, metotlar) implementasyondur; kullanıcının gördüğü DOM — metinler, roller, kilitli butonlar — davranıştır. İç duruma bağlanan test (component.acikMi okumak) davranışı koruyan refactor'da kırılır ve asıl hatayı — durum doğru ama ekran yanlış — kaçırır; kırılgan testin frontend hâlidir. İlke, doğrulamayı kullanıcının erişebildiği yüzeyden yapmaktır: "butona basılınca hata metni görünür" gibi. Testing Library bunu sorgu önceliğiyle doktrine çevirir: önce getByRole (erişilebilirlik ağacından rol + erişilebilir isim — ekran okuyucunun gördüğü; semantik HTML yatırımının karşılığı), sonra getByLabelText (form alanını etiketiyle bulur, label bağını da doğrular), sonra görünen metin sorguları; getByTestId son çaredir çünkü kullanıcı test-id göremez. Asenkron sonuç için findBy*/waitFor, yokluk doğrulaması için queryBy* kullanılır. Aynı ilke Angular'da elle uygulanır: assert'ler componentInstance'a değil nativeElement DOM'una yapılır. Sınır da bilinir: jsdom bir taklittir — gerçek yerleşim ve tarayıcı davranışının nihai kanıtı E2E katmanındadır.

Angular'da TestBed/ComponentFixture nasıl çalışır, detectChanges neden kritik? HttpTestingController ve fakeAsync ne sağlar?

TestBed, test içinde küçük bir Angular ortamı kurar: standalone bileşen imports ile alınır, DI konteyneri çalışır — sınır servisleri providers içinde sahteyle değiştirilir (entegrasyon dersindeki "yalnız sınırı değiştir" deseni). createComponent bir ComponentFixture verir: componentInstance sınıf, nativeElement DOM. Kritik nokta, değişiklik algılamanın testte otomatik olmamasıdır: durumu değiştirdikten sonra fixture.detectChanges() çağrılmazsa DOM eski kalır — "testim eski değeri görüyor" hatalarının bir numaralı nedeni. HttpTestingController, gerçek arka ucu test kontrollü bir kuyrukla değiştirir: expectOne ile beklenen istek yakalanır, metodu/gövdesi doğrulanır, flush ile cevap test tarafından verilir; afterEach'te verify() karşılanmamış ya da beklenmedik istekleri her testte yakalayan disiplindir. fakeAsync testi sahte zaman bölgesinde koşturur: tick(300) sanal zamanı ilerletir (debounce'lı arama beklenmeden test edilir), flush bekleyen zamanlayıcıları boşaltır — .NET tarafındaki FakeTimeProvider.Advance ile aynı fikir; gerçek setTimeout bekleyen test kararsızdır. Karma'nın 2023'te kullanımdan kaldırıldığını, Jasmine + TestBed bilgisinin ise koşucudan bağımsız geçerli kaldığını söylemek güncellik gösterir.

MSW nedir, fetch/axios'u doğrudan mock'lamaktan neden üstündür? Handler yönetiminde izolasyon nasıl korunur?

MSW (Mock Service Worker), ağı istek seviyesinde keser: bileşen gerçekten HTTP isteği atar, MSW tanımlı handler'la (http.get('/api/ilanlar', ...)) cevabı verir; testte setupServer ile Node içinde çalışır. fetch/axios'u fonksiyon olarak mock'lamak iki kuralı ihlal eder: sahip olmadığın türü mock'lamış olursun (kütüphanenin gerçek davranışını varsayarsın) ve test, bileşenin veri çekme biçimine bağlanır — axios'tan fetch'e geçiş gibi davranışı değiştirmeyen bir refactor tüm testleri kırar. MSW'de ise sözleşme HTTP seviyesindedir: bileşen ve veri katmanı hiç değişmeden test edilir, aynı handler'lar geliştirme ortamında ve Storybook'ta da kullanılabilir. İzolasyon deseni: varsayılan mutlu yol handler'ları bir kez kurulur (beforeAll(listen)); test kendi senaryosunu server.use(...) ile üstüne yazar (500, boş liste, gecikme); afterEach(resetHandlers) her testten sonra eklenenleri silerek "her test kendi ortamını kurar" kuralını korur; afterAll(close) kapatır. Negatif senaryoların (hata cevabı, zaman aşımı) mutlu yol kadar test edilmesi burada da geçerlidir — kullanıcının 500'de ne gördüğü de bir davranıştır.

jest.mock hoisting tuzağı nedir? Modül önbelleği test izolasyonunu nasıl bozar, hangi araçlarla düzeltilir ve snapshot testi neden çürür?

jest.mock çağrıları, import edilen modül yüklenmeden sahtenin devreye girebilmesi için derleme adımında dosyanın en başına taşınır (hoisting). Bedeli: mock factory, dosyada sonradan tanımlanan değişkenlere erişemez — koştuğu anda henüz tanımlı değildirler; Jest yalnız mock önekli isimlere bilerek izin verir. Bunu bilmeyen, "değişkenim undefined" hatasını saatlerce kovalar. Modül önbelleği sorunu Node'un require önbelleğinin test hâlidir: modül tepesindeki her değişken singleton'dır ve aynı dosyanın testleri arasında paylaşılır — ikinci test birincinin kirlettiği durumla başlar, sıra bağımlılığı ve kararsızlık doğar. Araçlar: jest.resetModules() modül kaydını boşaltır (sonrasında dinamik import taze kopya verir), jest.isolateModules aynı işi tek blok için yapar; yapılandırmada clearMocks (çağrı kayıtları) / resetMocks (implementasyonlar da) / restoreMocks (spyOn orijinalleri) ayrımı bilinir ve asgari clearMocks açılır. Kalıcı ders: izolasyonu bozan paylaşılan durumdur, frontend'de modül tepesinde yaşar. Snapshot çürümesi: dev serileştirilmiş çıktı hangi davranışın beklendiğini söylemez; kırıldığında diff okunmaz, refleksle jest -u basılır — okunmadan onaylanan snapshot assert'süz testtir. Doz: küçük ve odaklı snapshot (hata mesajı, serileştirici çıktısı), tercihen inline; bileşen davranışı için sorgu tabanlı test her zaman üstündür.

12Sınav köşesi

Yazılıda nasıl sorulur

(1) Frontend birim testi hangi araçlarla yazılır? (2) Jasmine ve Karma nedir, aralarındaki iş bölümü nedir? (3) Angular'da TestBed ne işe yarar? (4) HTTP istekleri Angular testlerinde nasıl taklit edilir? (5) Jest nedir, hangi amaçla kullanılır? (6) React Testing Library'nin test yaklaşımı nedir? (7) Snapshot testi nedir, avantajları ve sakıncaları nelerdir? (8) Testlerde asenkron işlemler nasıl beklenir? (9) Mock Service Worker (MSW) ne için kullanılır? (10) Frontend testlerinde izolasyon nasıl sağlanır?

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

Düzen: (1) İlke — "Frontend testinde iç durumu değil kullanıcının gördüğünü test ederim: butonun disabled'ı, görünen hata metni. İç alana bağlanan test refactor'da kırılır, gerçek hatayı kaçırır." (2) Angular — "TestBed ile bileşeni kurar, sınır servislerini providers'ta değiştiririm; detectChanges'in testte elle tetiklendiğini bilirim. HTTP'yi HttpTestingController ile karşılar, afterEach'te verify çağırırım; zamanı fakeAsync/tick ile sanal ilerletirim. Karma'nın kullanımdan kalktığını, Jasmine + TestBed bilgisinin koşucudan bağımsız olduğunu söylerim." (3) React — "Jest + Testing Library kullanırım: getByRole önceliğiyle erişilebilirlik ağacından sorgularım, etkileşimi user-event ile üretir, asenkronu findBy/waitFor ile beklerim." (4) Ağ — "fetch/axios'u mock'lamam; MSW ile ağı istek seviyesinde keserim — veri katmanı refactor'unda testler ayakta kalır, 500 senaryosunu da mutlu yol kadar test ederim." (5) Kıdem vuruşu — "Jest'te jest.mock'un hoist edildiğini ve factory'nin dış değişken göremediğini, modül tepesindeki durumun testler arası sızdığını bilirim — resetModules/isolateModules ve clearMocks sigortalarım. Snapshot'ı da küçük ve inline tutarım: okunmadan -u ile güncellenen snapshot, assert'süz testtir."