# 32. Hafta — Hata Ayıklama ve Test

## Bu hafta ne yapacağız?

Çalışıyor görünen bir hesaplamanın neden yanlış sonuç üretebildiğini inceleyeceğiz. Hesaplama kodunu arayüzden ayıracak, normal değerlerin yanında sınır ve geçersiz değerleri test edeceğiz. Ardından aynı yaklaşımı ağırlıklı not hesabı yapan özgün bir uygulamada kullanacağız.

## Kazanımlar

- Sözdizimi, çalışma zamanı ve mantık hatalarını ayırt etme
- Hesaplama fonksiyonunu widget kodundan ayırma
- `tryParse` ile kullanıcı girdisini güvenli dönüştürme
- `ArgumentError` ile sözleşme dışı değerleri reddetme
- Birim testi ve widget testinin görevlerini ayırt etme
- Normal, sınır ve geçersiz test verileri seçme
- Flutter golden testiyle gerçek arayüz çıktısını doğrulama

## Hata türleri

| Tür | Örnek | Nasıl bulunur? |
|---|---|---|
| Sözdizimi | Kapanmayan parantez | Derleyici mesajı |
| Çalışma zamanı | `null` değerde işlem | Hata yığını ve tekrar üretme |
| Mantık | Yüzdeyi 100’e bölmemek | Beklenen–gerçek sonuç karşılaştırması |
| Sınır | 100 indirimde negatif sonuç | Sınır değer testi |
| Doğrulama | “abc” metnini sayıya çevirmek | Geçersiz girdi testi |

## Çözümlü uygulama — Hata Avcısı: İndirim

### Hatalı yaklaşım

```dart
final sonuc = fiyat - oran;
```

800 TL üründe yüzde 25 indirim, 775 TL değildir. Oran önce yüzdelik değere çevrilmelidir.

### Düzeltilmiş ve doğrulanan fonksiyon

```dart
double indirimliTutar({
  required double fiyat,
  required double oran,
}) {
  if (fiyat < 0) throw ArgumentError('Fiyat negatif olamaz');
  if (oran < 0 || oran > 100) {
    throw ArgumentError('İndirim oranı 0–100 arasında olmalı');
  }
  return fiyat * (1 - oran / 100);
}
```

Fonksiyon arayüzden bağımsız olduğu için küçük ve hızlı bir birim testiyle denetlenebilir.

### Girdiyi güvenli okuma

```dart
final f = double.tryParse(fiyat.text.replaceAll(',', '.'));
final o = double.tryParse(oran.text.replaceAll(',', '.'));

if (f == null || o == null) {
  setState(() {
    tutar = null;
    sonuc = 'Fiyat ve oran sayısal olmalı';
  });
  return;
}
```

`double.parse` geçersiz metinde hata fırlatırken `tryParse` null döndürür. Formlarda kullanıcıya anlaşılır geri bildirim vermek için bu davranış daha uygundur.

### Birim testi

```dart
test('indirim formülü ve sınırları doğrudur', () {
  expect(indirimliTutar(fiyat: 800, oran: 25), 600);
  expect(indirimliTutar(fiyat: 800, oran: 0), 800);
  expect(indirimliTutar(fiyat: 800, oran: 100), 0);
  expect(
    () => indirimliTutar(fiyat: 100, oran: 101),
    throwsArgumentError,
  );
});
```

Yalnız 25 gibi normal bir değer değil, 0 ve 100 sınırları ile 101 geçersiz değeri de test edilir.

![Hata Avcısı gerçek Flutter ekranı](../../screenshots/week-32-adapted.png)

## Özgün uygulama — Testli Not Hesabı

### Sonuç modeli

```dart
class NotSonucu {
  const NotSonucu(this.ortalama, this.harf, this.gecti);

  final double ortalama;
  final String harf;
  final bool gecti;
}
```

Fonksiyon yalnız bir sayı değil, arayüzün ihtiyaç duyduğu bütün sonucu tek nesnede döndürür.

### Ağırlıklı ortalama ve sınırlar

```dart
for (final not in [sinav, proje, uygulama]) {
  if (not < 0 || not > 100) {
    throw ArgumentError('Notlar 0–100 arasında olmalı');
  }
}

final ortalama = sinav * .4 + proje * .25 + uygulama * .35;
```

Ağırlıkların toplamı 1’dir: `.40 + .25 + .35 = 1.00`.

### Harf notu

```dart
final harf = switch (ortalama) {
  >= 85 => 'A',
  >= 70 => 'B',
  >= 55 => 'C',
  >= 45 => 'D',
  _ => 'F',
};
```

Koşullar yüksek değerden düşüğe doğru yazılır. Ters sıralama yapılırsa örneğin 90 değeri ilk düşük koşula takılarak yanlış harf üretebilir.

### Test edilen davranışlar

```dart
final sonuc = notHesapla(
  sinav: 70,
  proje: 90,
  uygulama: 80,
);

expect(sonuc.ortalama, 78.5);
expect(sonuc.harf, 'B');
expect(sonuc.gecti, isTrue);
```

Ek testler negatif notu reddeder ve tam 50 ortalamanın geçme eşiğinde kabul edildiğini doğrular.

![Testli Not Hesabı gerçek Flutter ekranı](../../screenshots/week-32-original.png)

## Birim testi ve widget testi

- Birim testi hesaplama fonksiyonunu doğrudan çağırır; hızlıdır ve hata kaynağını daraltır.
- Widget testi form alanına girilen verinin buton işlemiyle hesaplamaya ulaştığını ve sonucun ekranda gösterildiğini doğrular.
- Golden testi Flutter’ın render ettiği ekranı PNG olarak kaydeder; taşma, eksik metin ve görsel düzen sorunlarını görsel olarak denetlemeye yardım eder.

Tek bir test türü diğerlerinin yerine geçmez.

## Hata ayıklama adımları

1. Hatanın tekrar üretilebildiği en küçük girdiyi bulun.
2. Beklenen ve gerçek sonucu açıkça yazın.
3. Arayüzden bağımsız hesaplama fonksiyonunu doğrudan test edin.
4. Ara değerleri debugger veya kontrollü loglarla inceleyin.
5. Hatanın nedenini düzeltin; yalnız görünen sonucu yamamayın.
6. Hatanın tekrarını önleyen testi kalıcı bırakın.
7. Normal, sınır ve geçersiz değerleri yeniden çalıştırın.

## Üç uygulama görevi

### Kolay — KDV hesaplayıcı

Net fiyat ve KDV oranından brüt tutarı hesaplayın. 0 oranı, ondalıklı fiyat, negatif fiyat ve 100’den büyük oran için test yazın.

### Orta — Devamsızlık durumu

Toplam ders saati ve devamsızlıktan yüzde hesaplayın. Tam sınırda geçen/kalan öğrenciyi ve sıfır toplam saat hatasını test edin.

### İleri — Kademeli elektrik faturası

Farklı tüketim aralıklarında farklı birim fiyatlar uygulayın. Her kademe sınırının bir altını, kendisini ve bir üstünü parametreli testlerle doğrulayın.

## Kontrol listesi

- Hesaplama widget kodundan ayrılmış mı?
- Girdi dönüşümü `tryParse` ile güvenli mi?
- Fonksiyon geçersiz değerleri açıkça reddediyor mu?
- Normal değer için beklenen sonuç test edilmiş mi?
- 0, 50 ve 100 gibi sınır değerleri kapsanmış mı?
- Hata düzeltmesini koruyan kalıcı test var mı?
- Widget testi kullanıcı akışını doğruluyor mu?
- Ekran görüntüsü testten geçen gerçek uygulamaya mı ait?

## Geri bildirim ve çözüm erişimi

Öğrenci çözümünü gönderdikten sonra **İpucunu göster**, hatayı tekrar üretme ve sınır değer seçme yaklaşımını anlatır; tam fonksiyonu vermez. **Örnek çözümü göster**, gerçek hesaplama, doğrulama, birim ve widget testi kodlarını açar. İndirme bağlantıları testleriyle birlikte çalışan iki Flutter projesini sunar.

## Kaynak projeler

- Konu uygulaması: `08 - Cihaz Özellikleri ve Kalite/Uygulamalar/Uygulama-32-Hatalı Hesap Makinesi`
- Özgün uygulama: `08 - Cihaz Özellikleri ve Kalite/Uygulamalar/Ozgun-32-Testli Not Hesabı`
