Birim Test Yazma: Python ile pytest Temel Örnekleri
Yazılım Test ve Hata Ayıklama
Birim Test Yazma: Python ile pytest Temel Örnekleri

Giriş
Pytest, Python için popüler ve açık kaynaklı bir test framework'üdür; basit bir sözdizimi ile birim testleri yazmayı hızlandırır ve test keşfini otomatikleştirir. Temel kullanımda test fonksiyonları test_ ile başlayan dosya ve fonksiyon adlarıyla tanınır ve Python'un standart assert ifadeleri kullanılır (kaynak: GeeksforGeeks, Wikipedia).
Başlamadan önce: Kurulum ve proje yapısı
Basit bir kurulum için sanal ortam oluşturun ve pytest'i yükleyin:
python -m venv .venv
.venv/bin/activate # veya Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install pytest
Önerilen proje ağacı örneği:
- my_project/
- my_package/ (kodunuz)
- tests/ (test dosyaları)
- pyproject.toml veya setup.cfg
İlk testiniz: basit bir örnek
Aşağıdaki örnek, verilen bir metnin tersini alan fonksiyonu test eder. Test dosyaları test_ ile başlamalıdır.
my_package/utils.py
def reverse_text(text):
return text[::-1]
tests/test_reversal.py
from my_package.utils import reverse_text
def test_reverse_text():
assert reverse_text('python') == 'nohtyp'
Terminalde proje kökünde pytest komutunu çalıştırmak testleri keşfeder ve yürütür:
pytest
Pytest, test fonksiyonlarını otomatik olarak bulur ve çalıştırır; bu davranışla hızlı geri bildirim alırsınız (kaynak: GeeksforGeeks).
Fixture ile tekrar eden yapılandırmayı düzenleme
Fixture'lar, testlerinizde tekrar eden kurulum/temizlik adımlarını merkezi hale getirir. Örnek:
import pytest
@pytest.fixture
def sample_data():
return [1, 2, 3]
def test_sum(sample_data):
assert sum(sample_data) == 6
Fixture'ı parametre olarak test fonksiyonuna enjekte edebilirsiniz. Büyük projelerde fixture'lar conftest.py içerisinde paylaştırılır.
Parametrize ile aynı testi farklı verilerle çalıştırma
@pytest.mark.parametrize dekoratörü aynı testi farklı girdi/çıktılarla çalıştırmak için idealdir:
import pytest
from my_package.utils import reverse_text
@pytest.mark.parametrize("input_text,expected", [
("abc", "cba"),
("", ""),
("a", "a"),
])
def test_reverse_param(input_text, expected):
assert reverse_text(input_text) == expected
Hata durumlarını test etme
Beklenen bir istisnayı test etmek için pytest.raises kullanılır:
def divide(a, b):
return a / b
def test_divide_by_zero():
import pytest
with pytest.raises(ZeroDivisionError):
divide(1, 0)
Bağımlılıkları izole etme: monkeypatch ve mocking
Dış sistemlere veya çevresel değişkenlere bağlı kodları test ederken monkeypatch fixture'ı kullanabilirsiniz:
def get_api_key():
import os
return os.getenv('API_KEY')
def test_get_api_key(monkeypatch):
monkeypatch.setenv('API_KEY', 'test-key')
assert get_api_key() == 'test-key'
Daha karmaşık durumlar için unittest.mock veya üçüncü taraf kütüphaneler tercih edilebilir. Pytest, unittest ile uyumlu çalışır; mevcut testleri pytest altında çalıştırabilirsiniz (kaynak: O'Reilly).
Test coverage (kapsam) ölçümü
Test kapsamını ölçmek için yaygın bir yöntem pytest-cov eklentisini kullanmaktır. Örnek kurulum ve komut:
pip install pytest-cov
pytest --cov=my_package
Bu komut, testler çalışırken hangi satırların çalıştırıldığını gösterir; raporlar CI iş akışlarında kullanılabilir.
Küçük bir örnek proje: hesap makinesi (calculator)
Basit işlevleri test eden bir örnek proje yapısı ve testler:
my_package/calculator.py
def add(a, b):
return a + b
def divide(a, b):
if b == 0:
raise ValueError('division by zero')
return a / b
tests/test_calculator.py
from my_package.calculator import add, divide
import pytest
def test_add():
assert add(2, 3) == 5
def test_divide():
assert divide(6, 3) == 2
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(1, 0)
TDD'ye kısa giriş
Test-Driven Development (TDD) temelde üç adımdan oluşur: kırmızı (test yaz, başarısız olsun), yeşil (en az kodla testi geç), refactor (temizle). Küçük adımlarla ilerlemek, tasarımın testlerle doğrulanmasını sağlar.
Pratik ipuçları ve iyi uygulamalar
- Testlerin deterministik olmasına dikkat edin; rastgelelik gerekiyorsa tohum (seed) sabitleyin.
- Her test bir mantıksal beklenti doğrulasın; büyük tek testlerden kaçının.
- Fixture'ları tekrar eden kurulum/temizlik için kullanın.
- Parametrize ile çoğalan testleri kısaltın ve okunabilirliği koruyun.
- CI/CD hattında testleri otomatik çalıştırın ve coverage raporlarını entegre edin.
- Dış bağımlılıkları izole etmek için monkeypatch veya mock kullanın.
Yaygın pytest komutları
- pytest — tüm testleri çalıştırır.
- pytest -q — daha kısa, daha sessiz çıktı verir.
- pytest -k 'expr' — isimde belirli bir ifadeyi içeren testleri çalıştırır.
- pytest -x veya pytest --maxfail=1 — ilk başarısız testte durur.
- pytest -q -s — print çıktılarının görünmesini sağlar.
- pytest --cov=package — pytest-cov ile kapsam raporu üretir.
Hata ayıklama ve çıktı analizi
Test başarısız olduğunda pytest, hatanın izini (traceback) gösterir. --tb=short gibi bayraklarla traceback formatını değiştirebilirsiniz. Hata mesajlarını anlamlı tutmak için assertta açıklayıcı koşullar yazmak yardımcı olur.
Özet ve kaynaklar
Bu rehberde pytest ile temel birim test yazımı, fixture ve parametrizasyon kullanımı, istisna testleri ve test coverage ölçümü gibi konuları örnek python kod snippetleriyle gösterdik. Daha derin bilgiler ve ileri seviye kullanım için resmi dökümantasyon ve kapsamlı kaynaklar faydalıdır:
Örnekler öğretici amaçlıdır; gerçek projelerde yapılandırma, paket adı alanları ve sürüm farklılıklarını göz önünde bulundurun.