Python İle Pytest Kullanarak Apı Uç Noktaları İçin Entegrasyon Testi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Test ortamınızı kurmak için öncelikle Python 3.12 veya üzeri bir sürümün yüklü olduğundan emin olun. Pytest, Python dünyasındaki en güçlü test framework'lerinden biridir. Bağımlılık yönetimi için pip aracını kullanacağız. Aşağıdaki komutlarla gerekli kütüphaneleri projenize dahil edin:

pip install pytest pytest-cov httpx

Burada httpx kütüphanesini tercih etmemizin sebebi, asenkron (async) istekleri desteklemesi ve modern Python standartlarıyla tam uyumlu olmasıdır. pytest-cov ise testlerinizin kod kapsamını (code coverage) ölçmenize olanak tanır.

Test Projesi Yapılandırması

Düzenli bir test yapısı, ölçeklenebilir projelerin temelidir. Projenizin kök dizininde tests/ adında bir klasör oluşturun. Pytest, test_*.py veya *_test.py ile başlayan dosyaları otomatik olarak algılar. Aşağıdaki örnekte, basit bir kullanıcı kayıt API'sini test edeceğiz.

# tests/conftest.py
import pytest
from httpx import AsyncClient
from main import app

@pytest.fixture
async def client():
    async with AsyncClient(app=app, base_url="http://test") as ac:
        yield ac

conftest.py dosyası, Pytest'in "fixture" (test öncesi hazırlık) mekanizmasını merkezi bir yerden yönetmenizi sağlar. Yukarıdaki kod, her test fonksiyonu için izole bir HTTP istemcisi oluşturur.

API Uç Noktaları İçin İlk Testi Yazma

Bir API uç noktasının doğru çalışıp çalışmadığını anlamak için HTTP durum kodlarını ve dönen JSON verisini kontrol etmemiz gerekir. Aşağıdaki örnekte, bir POST /users isteğinin başarılı olup olmadığını test ediyoruz.

# tests/test_api.py
import pytest

@pytest.mark.asyncio
async def test_create_user(client):
    payload = {"username": "testuser", "email": "test@example.com"}
    response = await client.post("/users", json=payload)
    
    assert response.status_code == 201
    assert response.json()["username"] == "testuser"

Bu test, API'nizin 201 (Created) durum kodu döndürüp döndürmediğini ve dönen verinin gönderilen veriye uygunluğunu doğrular. @pytest.mark.asyncio dekoratörü, fonksiyonun asenkron olarak çalıştırılmasını sağlar.

Veritabanı Entegrasyon Testleri ve Güvenlik

Entegrasyon testlerinde en büyük zorluk, veritabanı durumunu yönetmektir. Testler sırasında gerçek veritabanınızı bozmamak için mutlaka "test veritabanı" kullanmalısınız. Ayrıca, asla testlerde gerçek kullanıcı parolaları kullanmayın.

# Güvenli test verisi kullanımı
def test_login_security(client):
    # Parola asla açık metin olarak test edilmemelidir
    login_data = {"username": "admin", "password": "secure_password_123"}
    response = client.post("/login", json=login_data)
    
    # Başarısız giriş denemeleri için 401 kontrolü
    assert response.status_code == 401

Kritik Uyarı: Test ortamında asla üretim veritabanına bağlanmayın. Test veritabanınızı her test çalıştırılmadan önce temizleyen veya "rollback" (geri alma) yapan bir mekanizma kurun. SQL Injection riskine karşı, testlerinizde her zaman parametreli sorgular veya ORM modelleri kullanın.

Test Yöntemlerinin Karşılaştırılması

API testlerinde kullanılan farklı yaklaşımların avantaj ve dezavantajlarını aşağıdaki tabloda inceleyebilirsiniz:

Yöntem Avantajı Dezavantajı
Mocking (Taklit) Çok hızlıdır, dış bağımlılık gerektirmez. Gerçek sistem davranışını tam yansıtmaz.
Entegrasyon Testi Gerçek veritabanı/servis etkileşimini test eder. Daha yavaştır, kurulum gerektirir.
E2E (Uçtan Uca) Kullanıcı akışını tamamen doğrular. Bakımı en zor ve en kırılgan olanıdır.

Yaygın Hatalar ve Debug İpuçları

API testlerinde en sık karşılaşılan hata, testlerin birbirini etkilemesidir. Eğer bir testin oluşturduğu veri, diğer testin başarısız olmasına neden oluyorsa, testleriniz "izole" değildir. Her test, kendi verisini oluşturmalı ve işlem bittiğinde temizlemelidir.

# Test sonrası temizlik örneği
@pytest.fixture(autouse=True)
def cleanup_database():
    # Test öncesi hazırlık
    yield
    # Test sonrası veritabanını temizle
    db.execute("DELETE FROM users WHERE username='testuser'")

Hata ayıklama (debug) yaparken pytest -s komutunu kullanın. Bu, test içindeki print() ifadelerinin konsola yansımasını sağlar; böylece dönen yanıtın içeriğini anlık olarak görebilirsiniz.

Sıkça Sorulan Sorular

Entegrasyon testlerini ne sıklıkla çalıştırmalıyım?

Her kod değişikliğinden (commit) sonra ve CI/CD süreçlerinde otomatik olarak çalıştırılmalıdır.

Testlerimde neden 403 Forbidden hatası alıyorum?

Genellikle test isteğinde gerekli olan yetkilendirme (token/header) eksik gönderilmiştir. İsteğinize uygun Bearer token eklediğinizden emin olun.

Pytest ile nasıl performans testi yaparım?

pytest-benchmark eklentisini kullanarak uç noktalarınızın yanıt sürelerini ölçebilirsiniz.

Veritabanı bağımlılığını nasıl yönetirim?

Docker kullanarak test anında geçici bir veritabanı konteyneri ayağa kaldırmak en temiz yöntemdir.

Test kapsamı (coverage) ne kadar olmalı?

İdeal olan %80 ve üzeridir, ancak kritik finansal veya güvenlik uç noktalarında %100 hedeflenmelidir.

İleri Seviye Test Stratejileri: Parametrik Testler ve Mocking

Testlerinizi daha verimli hale getirmek için Pytest'in sunduğu @pytest.mark.parametrize dekoratörünü kullanmak, aynı test mantığını farklı veri setleriyle defalarca çalıştırmanızı sağlar. Bu yöntem, özellikle API uç noktalarınızın farklı girdi kombinasyonlarına (geçerli/geçersiz veriler) nasıl tepki verdiğini doğrulamak için mükemmeldir.

Aşağıdaki örnekte, bir kullanıcı oluşturma uç noktasının farklı yaş değerleri için nasıl test edileceğini görebilirsiniz:

import pytest
import requests

@pytest.mark.parametrize("age, expected_status", [
    (25, 201),
    (17, 400),
    (-5, 400),
    (150, 400)
])
def test_create_user_age_validation(api_client, age, expected_status):
    payload = {"username": "testuser", "age": age}
    response = api_client.post("/users", json=payload)
    assert response.status_code == expected_status

Ayrıca, dış servis bağımlılıklarını (örneğin bir ödeme geçidi veya üçüncü taraf bir e-posta servisi) test ederken unittest.mock kütüphanesini kullanarak bu servisleri simüle etmelisiniz. Bu, testlerinizin dış ağ bağımlılıklarından kurtulmasını ve çok daha hızlı çalışmasını sağlar.

Test Süreçlerinde CI/CD Entegrasyonu ve Raporlama

Entegrasyon testlerinin manuel olarak çalıştırılması hata payını artırır. Testlerinizi her git push işleminde otomatik olarak çalışacak bir CI/CD hattına (GitHub Actions gibi) entegre etmek, kod kalitesini standartlaştırır. Test sonuçlarını görselleştirmek için pytest-html eklentisini kullanarak her test çalışmasından sonra detaylı bir rapor dosyası oluşturabilirsiniz.

GitHub Actions üzerinde testleri çalıştırmak için .github/workflows/test.yml dosyanıza şu adımları ekleyebilirsiniz:

name: API Integration Tests
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.9'
      - name: Install dependencies
        run: pip install pytest requests
      - name: Run tests
        run: pytest --html=report.html

Test Raporlarını Okuma ve Analiz Etme

Testleriniz başarısız olduğunda, sadece hata mesajına odaklanmak yerine pytest --tb=short komutu ile hata izleme (traceback) çıktısını sadeleştirebilirsiniz. Eğer testlerinizde karmaşık veri yapıları dönüyorsa, pytest-clarity eklentisini kurarak hata anındaki değişkenlerin durumunu çok daha okunaklı bir formatta görebilirsiniz.

Komut Açıklama
pytest -v Testleri detaylı (verbose) modda çalıştırır.
pytest -k "login" Sadece isminde "login" geçen testleri çalıştırır.
pytest --maxfail=3 3 hata alındığında test sürecini durdurur.

Bu ileri seviye yaklaşımlar, API geliştirme sürecinizde karşılaştığınız belirsizlikleri azaltacak ve test odaklı geliştirme (TDD) disiplinini projenizin merkezine yerleştirmenize yardımcı olacaktır.

Sonuç

Python ve Pytest ile API entegrasyon testleri yazmak, projenizin uzun vadeli başarısı için atılacak en önemli adımlardan biridir. Bu rehberde öğrendiğiniz teknikleri (fixture kullanımı, veritabanı izolasyonu ve HTTP istemcisi yönetimi) uygulayarak, daha sağlam ve güvenilir API'ler geliştirebilirsiniz. Bir sonraki adım olarak, bu testleri GitHub Actions veya GitLab CI gibi bir sürekli entegrasyon hattına dahil ederek otomasyonu tamamlamanızı öneririm.

Sorumluluk Reddi: Bu kılavuzdaki kod örnekleri eğitim amaçlıdır. Yazılım güvenliği sorumluluğu geliştiriciye aittir. Üretim ortamına kod dağıtmadan önce tüm güvenlik açıklarını taradığınızdan ve hassas verileri (API anahtarları, şifreler) ortam değişkenlerinde (environment variables) sakladığınızdan emin olun.

Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Hobi projeleri ve kendin yap (DIY) içerikleri üzerine uzmanlaşmış bir içerik editörüyüm. Adım adım rehberlerle okuyucuların teknik becerilerini geliştirmelerine yardımcı oluyorum.

Yorumlar (0)

Yorum Yaz