Gereksinimler ve Ön Hazırlık
Çalışmalara başlamadan önce sisteminizde Python 3.10 veya üzeri bir sürümün yüklü olması önerilir. Pytest, Python ekosistemindeki en popüler test aracıdır ve kurulumu oldukça basittir. Terminalinizi açarak aşağıdaki komutla kütüphaneyi sanal ortamınıza (virtual environment) dahil edebilirsiniz.
pip install pytest
Kurulumun başarılı olduğunu doğrulamak için terminalde pytest --version komutunu çalıştırın. Ayrıca projelerinizde bağımlılıkları yönetmek için requirements.txt dosyası kullanmanız, takım çalışmasında standart bir yapı sağlar.
Temel Bir Test Fonksiyonu Yazımı
Pytest, test dosyalarını otomatik olarak keşfetmek için dosya isimlerinin test_ ile başlamasını veya _test.py ile bitmesini bekler. İlk testinizi yazarken, test etmek istediğiniz fonksiyonun mantığını basit tutmak önemlidir.
# hesaplama.py
def topla(a, b):
return a + b
# test_hesaplama.py
from hesaplama import topla
def test_topla_dogru_sonuc_vermeli():
assert topla(2, 3) == 5
assert topla(-1, 1) == 0
Burada assert anahtar kelimesi, Python'un yerleşik hata kontrol mekanizmasıdır. Eğer assert ifadesinden sonra gelen koşul yanlışsa, Pytest testi başarısız olarak işaretler ve detaylı bir hata raporu sunar.
Pytest ile Testleri Çalıştırma ve Analiz Etme
Testlerinizi yazdığınıza göre artık onları çalıştırma vakti geldi. Terminalde proje dizinindeyken sadece pytest yazmanız yeterlidir. Pytest, dizin yapısını tarar ve tüm test dosyalarını otomatik olarak çalıştırır.
Test sonuçlarını daha detaylı görmek isterseniz pytest -v (verbose/ayrıntılı) komutunu kullanabilirsiniz. Bu komut, hangi testin geçtiğini ve hangisinin hata verdiğini satır satır listeler.
# Testleri çalıştırmak için terminal komutu:
pytest -v
Testleriniz başarısız olduğunda Pytest, hata anındaki değişken değerlerini ve kodun hangi satırında kırılma yaşandığını gösterir. Bu, hata ayıklama (debugging) sürecini ciddi oranda hızlandırır.
Fixtures (Fikstürler) Kullanımı
Testlerinizde sürekli kullandığınız veritabanı bağlantıları, dosya okuma işlemleri veya yapılandırma ayarları varsa, bunları her test fonksiyonunda baştan tanımlamak yerine @pytest.fixture dekoratörünü kullanırız. Bu, kod tekrarını önler ve testlerinizi daha temiz hale getirir.
import pytest
@pytest.fixture
def ornek_kullanici():
return {"id": 1, "isim": "Ahmet", "rol": "admin"}
def test_kullanici_rolu(ornek_kullanici):
assert ornek_kullanici["rol"] == "admin"
Bu örnekte ornek_kullanici fonksiyonu bir fikstürdür. Test fonksiyonuna parametre olarak geçtiğimizde, Pytest bu fonksiyonu otomatik olarak çağırır ve dönen değeri testin içine enjekte eder.
Parametrik Testler ile Verimlilik
Aynı fonksiyonu farklı verilerle test etmek istediğinizde, her veri için ayrı bir test fonksiyonu yazmak yerine @pytest.mark.parametrize dekoratörünü kullanmalısınız. Bu, test kapsamını genişletirken kod satırı sayısını minimumda tutar.
import pytest
@pytest.mark.parametrize("a, b, beklenen", [
(1, 2, 3),
(5, 5, 10),
(0, 0, 0),
(-1, 1, 0)
])
def test_topla_coklu_durum(a, b, beklenen):
assert topla(a, b) == beklenen
Bu yöntemle, tek bir fonksiyon içerisinde onlarca farklı senaryoyu test edebilirsiniz. Her bir veri seti, Pytest tarafından ayrı bir test vakası olarak raporlanır.
Test Yöntemleri Karşılaştırması
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Standart Assert | Hızlı ve basit | Karmaşık nesnelerde yetersiz kalabilir |
| Fixtures | Kod tekrarını önler, temizdir | Öğrenme eğrisi gerektirir |
| Parametrizasyon | Yüksek kapsam, az kod | Hata durumunda hangi verinin patladığını takip etmek gerekir |
Güvenlik Uyarısı: Birim testleri yazarken asla canlı veritabanı veya gerçek kullanıcı verileriyle çalışmayın. Testleriniz için her zaman izole edilmiş (mock) veriler veya geçici test veritabanları kullanın. Aksi takdirde, yanlışlıkla gerçek verileri silebilir veya sızıntılara yol açabilirsiniz.
Sıkça Sorulan Sorular
Pytest neden unittest yerine tercih edilmeli?
Pytest, daha az "boilerplate" (gereksiz kod) gerektirir, daha okunabilir hata mesajları sunar ve eklenti desteği sayesinde çok daha geniş bir ekosisteme sahiptir.
Test dosyalarımı nereye koymalıyım?
Genel kabul gören standart, proje kök dizininde tests/ adında bir klasör oluşturmak ve test dosyalarını bu klasörün içinde tutmaktır.
Testlerimi nasıl izole edebilirim?
unittest.mock kütüphanesini kullanarak dış servis çağrılarını veya veritabanı işlemlerini taklit edebilir, kodunuzun sadece kendi mantığına odaklanmasını sağlayabilirsiniz.
Pytest'te testleri nasıl gruplandırabilirim?
@pytest.mark dekoratörlerini kullanarak testlerinizi "hızlı", "yavaş", "veritabani" gibi kategorilere ayırabilir ve sadece istediğiniz grubu çalıştırabilirsiniz.
Test coverage (kapsam) nedir?
Testlerinizin kodunuzun ne kadarını çalıştırdığını ölçen bir metriktir. pytest-cov eklentisi ile bu oranı yüzde olarak takip edebilirsiniz.
Sorumluluk Reddi: Bu makalede yer alan kod örnekleri eğitim amaçlıdır. Yazılım geliştirme sürecinde güvenlik açıklarını önlemek için her zaman güncel kütüphaneleri takip edin ve giriş verilerini doğrulama (input validation) pratiklerini asla ihmal etmeyin.
Pytest ile Hata Ayıklama (Debugging) Stratejileri
Testleriniz başarısız olduğunda, hatanın kaynağını hızlıca tespit etmek geliştirme hızınızı doğrudan etkiler. Pytest, hata ayıklama sürecini kolaylaştıran yerleşik araçlar sunar. Özellikle --pdb (Python Debugger) bayrağı, test başarısız olduğu anda kodun o satırında duraklamanızı sağlar.
Bir testin hata anında duraklaması için terminalde şu komutu çalıştırabilirsiniz:
pytest --pdb
Bu komut, hata gerçekleştiği anda sizi etkileşimli bir kabuğa sokar. Burada değişkenlerin değerlerini kontrol edebilir, fonksiyon çağrılarını inceleyebilir ve hatanın nedenini anlık olarak gözlemleyebilirsiniz. Ayrıca, pytest.set_trace() fonksiyonunu kodunuzun içine yerleştirerek belirli bir noktada manuel olarak hata ayıklama modunu tetikleyebilirsiniz:
import pytest
def test_hesaplama():
sonuc = 10 / 0 # Burada bir hata oluşacak
# pytest.set_trace() # İsterseniz buraya breakpoint koyabilirsiniz
assert sonuc == 1
Pytest ile Performans Testleri ve Zaman Aşımı
Birim testlerinizin hızlı çalışması, geliştirme döngüsü için kritiktir. Bazen bir fonksiyonun beklenenden çok daha uzun sürede tamamlanması, kodda bir performans darboğazı veya sonsuz döngü olduğunun işareti olabilir. Pytest ile belirli bir süreyi aşan testleri tespit etmek için pytest-timeout eklentisini kullanabilirsiniz.
Eklentiyi kurduktan sonra, testlerinize dekoratörler ekleyerek zaman aşımı sınırları belirleyebilirsiniz:
import pytest
import time
@pytest.mark.timeout(2) # Test 2 saniyeden uzun sürerse başarısız sayılır
def test_uzun_suren_islem():
time.sleep(3)
assert True
Ayrıca, testlerinizin ne kadar sürede tamamlandığını görmek için --durations parametresini kullanmak, projenizdeki "yavaş" testleri listelemenize yardımcı olur:
pytest --durations=5
Bu komut, en yavaş 5 testi süreleriyle birlikte raporlayacaktır. Bu yöntem, özellikle veritabanı veya ağ bağlantısı gerektiren testlerin optimize edilmesinde oldukça etkilidir.
Testlerde Mocking Kullanımı
Dış servislere (API, veritabanı, dosya sistemi) bağımlı olan kodları test ederken, bu servisleri taklit etmek (mocking) testlerinizi izole ve hızlı tutar. Python'un standart unittest.mock kütüphanesi, Pytest ile mükemmel bir uyum içinde çalışır.
from unittest.mock import MagicMock
def test_api_cagrisi():
# Bir API istemcisini taklit ediyoruz
api_client = MagicMock()
api_client.get_data.return_value = {"status": "success", "data": 100}
sonuc = api_client.get_data()
assert sonuc["data"] == 100
api_client.get_data.assert_called_once()
Bu yaklaşım sayesinde, gerçek bir API'ye bağlanmadan kodunuzun mantıksal akışını test edebilir, ağ hatalarından bağımsız bir test ortamı oluşturabilirsiniz.
Sonuç
Python ile Pytest kullanarak birim testi yapmak, projenizin sürdürülebilirliğini ve güvenilirliğini artıran en önemli adımdır. Bu rehberde temel test yazımından, parametrizasyona ve fikstür kullanımına kadar temel yetkinlikleri kazandınız. Bir sonraki adım olarak, projenizde pytest-cov eklentisini kurarak test kapsamınızı raporlamayı ve CI/CD süreçlerinize otomatik testleri dahil etmeyi deneyebilirsiniz. Yazılım kalitesini artırmak sürekli bir süreçtir; küçük testlerle başlayıp büyük sistemler inşa edebilirsiniz.

Yorumlar (0)
Yorum Yaz