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.mockhoisting, 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:
| Öncelik | Sorgu | Neden |
|---|---|---|
| 1 | getByRole('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 |
| 2 | getByLabelText('E-posta') |
Form alanını etiketiyle — label bağını da bedavaya doğrular |
| 3 | getByText, getByPlaceholderText |
Görünen metin; kullanıcının okuduğu şey |
| son çare | getByTestId('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)
- 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.
- Kullanıcı gözü testi. (React) RTL ile üç davranışı
getByRole/findByTextsorgularıyla test et;getByTestId'yi yalnız gerçekten gerekirse kullan. (Angular) Aynı üçlüyü TestBed ile yaz; assert'lericomponentInstancealanlarına değilnativeElementDOM'una yap ve her durum değişiminden sonradetectChangesçağır. - 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.
- İzolasyon deneyi. Modül seviyesinde durum tutan küçük bir modül yaz (sayaç);
iki testin birbirini kirlettiğini gör,
jest.resetModules+ dinamikimportile düzelt. 12-03'teki önbellek bilgisiyle bağını bir cümleyle not et. - 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."
