Python İle Pytest Kütüphanesi Kullanarak Birim Testi Nasıl Yapılır?

Python İle Pytest Kütüphanesi Kullanarak Birim Testi Nasıl Yapılır?
Python İle Pytest Kütüphanesi Kullanarak Birim Testi Nasıl Yapılır?

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.

Bu yazıya tepkinizi paylaşın:
Burak Şahin

Verimlilik ve organizasyon üzerine uzmanlaşmış bir yazarım. Karmaşık görevleri yönetilebilir parçalara bölerek okuyucunun zamanını doğru kullanmasını sağlıyorum.

Yorumlar (0)

Yorum Yaz