10 - Birim Test, Test Güdümlü Geliştirme (TDD) ve Debugging
2026
Bu hafta:
Neden kullanırız?
unittest Modülüunittest, Python’un standart test kütüphanesidir.Temel adımlar:
unittest.TestCase sınıfından türeyen bir test sınıfı yazılır.test_ ile başlayan test metotları tanımlanır.unittest ile Basit Bir ÖrnekKodumuz (matematik.py):
test_matematik.py)import unittest
from matematik import topla
class TestToplama(unittest.TestCase):
def test_iki_pozitif(self):
sonuc = topla(5, 3)
self.assertEqual(sonuc, 8)
def test_pozitif_negatif(self):
sonuc = topla(3, -5)
self.assertEqual(sonuc, -2)Terminalden çalıştırma:
Bir assertion başarısız olursa test de başarısız olur.
assertEqual(a, b) → a ile b eşit mi?assertNotEqual(a, b) → a ile b farklı mı?assertTrue(x) → x doğru mu?assertFalse(x) → x yanlış mı?assertIsNone(x) → x, None mı?assertIsNotNone(x) → x, None değil mi?assertRaises(HataTipi, fonksiyon, argümanlar...) → Beklenen hata oluşuyor mu?pytestpytest, daha sade yazımıyla öne çıkan popüler bir test aracıdır.unittest’e göre daha az kodla test yazılır.Avantajları:
assert ifadesi kullanılırKurulum:
pytest ile Yazmakfrom matematik import topla
def test_iki_pozitif():
sonuc = topla(5, 3)
assert sonuc == 8
def test_pozitif_negatif():
sonuc = topla(3, -5)
assert sonuc == -2Terminalden çalıştırma:
Bir string içindeki boşluk sayısını döndüren bosluk_say(metin) fonksiyonunuz olsun.
Bu fonksiyon için aklınıza gelen iki farklı test durumu ne olur?
Buna mocking denir.
Neden kullanırız?
# test_app.py
import unittest
from unittest.mock import patch, Mock
from app_code import get_kullanici_adi
class TestAPI(unittest.TestCase):
@patch("app_code.requests.get")
def test_kullanici_adi_getir(self, mock_get):
mock_response = Mock()
mock_response.json.return_value = {"name": "Ayşe"}
mock_get.return_value = mock_response
isim = get_kullanici_adi(5)
self.assertEqual(isim, "Ayşe")Bu örnekte asıl amaç, gerçek API’ye gitmeden fonksiyonun doğru değeri işleyip işlemediğini görmektir.
Yani burada hem çıktı hem de kullanım biçimi test edilmiş olur.
Bir fonksiyonun dosyaya log kaydı yazdığını düşünün.
Test sırasında gerçekten dosya oluşturmak istemiyorsanız, bu durumda hangi işlemi taklit etmek uygun olur?
open(...)write(...) işlemiAmaç:
Red
Önce başarısız olacak bir test yazılır.
Green
Testi geçirecek en basit kod yazılır.
Refactor
Kod iyileştirilir; testler hâlâ geçiyorsa devam edilir.
İstek: is_pozitif(sayi) fonksiyonu yazılsın.
Önce testi yazarız:
# test_sayi_kontrol.py
from sayi_kontrol import is_pozitif
def test_pozitif_icin_true():
assert is_pozitif(5) is TrueBu aşamada test başarısız olabilir; çünkü fonksiyon henüz yoktur ya da doğru yazılmamıştır.
Testi geçirecek en basit kod:
Yeni bir test ekleyelim:
# test_sayi_kontrol.py
from sayi_kontrol import is_pozitif
def test_pozitif_icin_true():
assert is_pozitif(5) is True
def test_negatif_icin_false():
assert is_pozitif(-3) is FalseArtık kodu düzeltmemiz gerekir:
Böylece her iki test de geçer.
Çünkü aynı hatanın benzeri daha sonra başka yerde tekrar ortaya çıkabilir.
print() ile Debuggingprint(...) satırları eklenerek değerler izlenir.def hesapla(a, b):
print(f"Girdi: a={a}, b={b}")
sonuc = a / b
print(f"Sonuç: {sonuc}")
return sonucAvantajı: Hızlı ve basit olması
Sınırlılığı: Büyük ve karmaşık kodlarda yetersiz kalması
VS Code, PyCharm gibi araçlardaki debugger’lar daha güçlüdür.
Temel özellikler:
Bu yöntem, özellikle karmaşık hatalarda daha kullanışlıdır.
pdb ve breakpoint()Python’da terminal tabanlı hata ayıklama için pdb kullanılabilir.
Daha güncel ve kısa kullanım ise şudur:
breakpoint(), uygun debugger’ı çağırırpdb ile çalışırpdb Komutların → bir sonraki satıra geçs → fonksiyonun içine girp degisken → değişkenin değerini yazdırc → programı devam ettirq → debugger’dan çıkBu komutlar, terminalde adım adım ilerleyerek hatayı incelemeyi sağlar.
Kendi bilgisayarınızda bir IDE kullanarak, karmaşık bir hesaplama hatasını inceleyeceğinizi düşünün.
İlk olarak hangisini tercih etmek daha uygun olur?
print() eklemekpdb kullanmakNot: Yerel geliştirme ortamında çoğu zaman (B) daha rahattır.
Ancak IDE olmayan bir sunucu ya da terminal ortamında (C) daha uygun olabilir.
unittest ve pytest, Python’da sık kullanılan test araçlarıdır.Bir metin_islemleri.py dosyasına ters_cevir(metin) fonksiyonunu yazın.
Ardından bu fonksiyon için test_metin.py dosyasında şu durumları test edin:
"python" → "nohtyp""" → """madam" → "madam"Aşağıdaki kod, listedeki en büyük sayıyı bulmaya çalışıyor. Ancak liste yalnızca negatif sayılardan oluştuğunda ve liste boş olduğunda sorun üretiyor.
Hatanın nerede olduğunu ve neden oluştuğunu bulun.
# hatali_kod.py
def en_buyuk_sayi(liste):
en_buyuk = 0
for sayi in liste:
if sayi > en_buyuk:
en_buyuk = sayi
return en_buyuk
sonuc1 = en_buyuk_sayi([1, 5, 2, 8, 3])
sonuc2 = en_buyuk_sayi([-1, -5, -2, -8, -3])
sonuc3 = en_buyuk_sayi([])
print(f"Pozitif Liste Sonuç: {sonuc1}")
print(f"Negatif Liste Sonuç: {sonuc2}")
print(f"Boş Liste Sonuç: {sonuc3}")İpucu: Başlangıç değeri ve boş liste durumu üzerinde düşünün.