Pytest fikstürleri

Tamamlandı

Fikstürler modüler, ölçeklenebilir ve sürdürülebilir testler oluşturmak için kullanılan pytest yardımcı işlevleridir. Veritabanı bağlantıları, test verileri oluşturma veya bir testin çalıştırılabilmesi için gereken sistem durumunu yapılandırma gibi testlerin önkoşullarını ayarlamak için fikstürleri kullanırsınız. Testler çalıştırıldıktan sonra temizleme için de kullanılabilirler.

Pytest fikstürlerinin temel özellikleri şunlardır:

  • Kapsam denetimi: Fikstürler, scopefikstürün function ne sıklıkta çağrıldığını belirleyen parametresi (, class, moduleveya sessiongibi) kullanılarak farklı kapsamlara sahip olacak şekilde yapılandırılabilir.
  • Kurulum ve yıkım işlemlerinin işlenmesi: Pytest, fikstürlerin yaşam döngüsünü yönetir, gerektiğinde otomatik olarak ayarlanır ve kaldırılır.
  • Bağımlılık ekleme: Fikstürler test işlevlerine bağımsız değişken olarak eklenir ve hangi testlerin hangi fikstürlere dayandığı netleştirilir.
  • Yeniden kullanılabilirlik ve modülerlik: Fikstürler tek bir yerde tanımlanabilir ve birden çok test işlevi, modül ve hatta projede kullanılabilir.

Geçici dosya fikstür oluşturma

Dosyalarla etkileşim kuran testler yazarken, test sonrası dosya sisteminde kalabalık yaratmamak için geçici dosyalara ihtiyaç duyulması yaygındır. Pytest ile geçici bir dosya ayarlayan bir fikstür oluşturabiliriz. Fikstür, python'ın tempfile modülünü kullanarak geçici dosyaları güvenli bir şekilde oluşturur ve yerel ortamı etkilemeden kullanılabilir ve silinebilir. (Fikstürümüzün bu ilk sürümünde, delete=False bayrağı nedeniyle dosya otomatik olarak silinmez. Dosya silme işlemini daha sonra ele alacağız.)

Fikstür şöyle görünür:

import pytest
import tempfile

@pytest.fixture
def tmp_file():
    def create():
        # Create a named temporary file that persists beyond the function scope
        temp = tempfile.NamedTemporaryFile(delete=False)
        return temp.name
    return create

Bu kurulumda, tmp_file() sabitleyici görevi görür. Fikstürün adı, testlerin ona atıfta bulunma şeklidir. Fikstürün içinde, iç içe işlev create(), fikstür kurulumu sırasında değil de yalnızca çağrıldığında dosyayı oluşturur. Bu, geçici dosyanın ne zaman oluşturulduğu üzerinde hassas denetime olanak tanır. Bu, zamanlama ve dosya durumunun kritik olduğu testlerde kullanışlıdır.

create()iç içe yerleştirilmiş işlev içinde geçici bir dosya oluşturulur ve ardından bu dosyanın mutlak yolu döndürülür. Aşağıda, bir testin yazdığımız fikstürden nasıl yararlanabileceğine ilişkin bir örnek verilmişti:

import os

def test_file(tmp_file):
    path = tmp_file()
    assert os.path.exists(path)

Test, bir fikstürü, fikstür adını bağımsız değişken olarak belirterek kullanır. Basit kullanım örneğimiz, dosyaya yazılarak veya izinleri veya sahipliği değiştirme gibi değişiklikler yaparak kolayca genişletilebilir.

Kapsam yönetimi

Pytest'te, kurulum ve yok etme yordamları aracılığıyla test kaynaklarının yaşam döngüsünü yönetmek, temiz ve verimli test ortamlarının korunması için çok önemlidir. Ayrıca, her testin bilinen ve tutarlı bir durumla başladığından emin olarak testlerin bütünlüğünü korumak istiyorsunuz. Varsayılan olarak, pytest fikstürleri davranışı iki şekilde etkileyen function bir kapsamla çalışır:

  • Test başına yaşam döngüsü: Fikstürün dönüş değeri, onu kullanan her test işlevi için yeniden hesaplanır ve her testin yeni bir durumla çalışmasını sağlar.
  • Her kullanımdan sonra temizleme: Fikstür kullanan her test sonrasında gerekli temizleme işlemleri gerçekleştirilir.

Pytest ayrıca performansı ve kaynak kullanımını iyileştirmek için fikstürlerin kapsamının daha geniş kapsamlı olmasını sağlar. Kapsam oluşturma özellikle veritabanı durumunu yönetme veya oluşturması zaman alan karmaşık durum kurulumları gibi durumlarda kullanışlıdır. Kullanılabilir dört kapsam şunlardır:

  • function: Varsayılan kapsam, fikstür test başına bir kez yürütülür
  • class: Fikstür, test sınıfı başına bir kez çalışır.
  • module: Modül için bir kez çalıştırılır.
  • session: Test oturumu başına bir kez çalışır. Bu kapsam, bir hizmeti başlatma veya veritabanı sunucusu başlatma gibi tüm test oturumu boyunca kalıcı olması gereken pahalı işlemler için kullanışlıdır.

Bu durumda, bir kez çalıştırılırsa, dönüş değeri önbelleğe alınır. Bu nedenle, "modül" kapsamına sahip bir fikstür, bir test modülünde birkaç kez çağrılabilir, ancak dönüş değeri, onu çağıran ilk testin değeridir.

modül kapsamıyla tmp_file() fikstür şöyle görünür:

import pytest
import tempfile

@pytest.fixture(scope="module")
def tmp_file():
    def create():
        temp = tempfile.NamedTemporaryFile(delete=False)
        return temp.name
    return create

Temizleme yönetimi

tmp_file fikstürünün belirtildiği önceki kod geçici bir dosya oluşturur, ancak testler tamamlandıktan sonra temizlemeyi otomatik olarak işlemez. Geçici dosyaların geride bırakılmadığından emin olmak için pytest'in request fikstür kullanarak temizleme işlevini kaydedebilirsiniz.

otomatik temizlemeyi dahil etmek için tmp_file fikstürünün nasıl değiştirileceği şöyledir:

import pytest
import tempfile
import os

@pytest.fixture(scope="module")
def tmp_file(request):
    # Create a temporary file that persists beyond the function scope
    temp = tempfile.NamedTemporaryFile(delete=False)

    def create():
        # Returns the path of the temporary file
        return temp.name

    def cleanup():
        # Remove the file after the tests are done
        os.remove(temp.name)

    # Register the cleanup function to be called after the last test in the module
    request.addfinalizer(cleanup)

    return create

request.addfinalizer() kullanılarak ve iç içe geçmiş cleanup() işlevi geçirilerek, temizleme, kapsamına bağlı olarak gerçekleştirilir. Bu durumda kapsam moduleolduğundan, bir modüldeki tüm testlerden sonra pytest bu temizleme işlevini çağırır.

conftest.py'yi kullanma

Fikstürlerinizi test dosyalarınıza dahil etmek yerine conftest.py dosyasına kaydedebilirsiniz. conftest.py'deki tüm fikstürler, testlerinizi açıkça içeri aktarmak zorunda kalmadan aynı dizinde otomatik olarak kullanılabilir.

Yerleşik armatürleri keşfetme

Pytest, testi kolaylaştırmak için tasarlanmış birçok yerleşik fikstüre sahiptir. Bu fikstürler kurulum ve temizleme işlemlerini otomatik olarak gerçekleştirerek test yönetimi yerine test çalışmalarınızı yazmaya odaklanmanızı sağlar.

Temel yerleşik fikstürler şunlardır:

  • cache: Test oturumları arasında veri depolamak için yararlı olan test düzeyinde önbellek oluşturmak ve yönetmek için kullanılır.
  • capsys: stderr ve stdoutdenetimine izin verir ve konsol çıkışlarını incelemeyi ve test etmenizi kolaylaştırır.
  • tmpdir: Testler sırasında oluşturulması ve kullanılması gereken dosyalar için geçici bir dizin sağlar.
  • monkeypatch: Nesnelerin, işlevlerin ve işletim sistemi ortamınızın davranışını ve değerlerini güvenli bir şekilde değiştirmenin bir yolunu sağlar.

Testte maymun eşleştirmenin rolü

Veritabanları veya dış API'ler gibi dış kaynaklarla sıkı bir şekilde tümleşen kodu test etmek, söz konusu bağımlılıklar nedeniyle zor olabilir. Maymun yaması olarak adlandırılan bir teknik, test çalışmaları sırasında sisteminizi geçici olarak değiştirmenizi içerir. Bu, dış sistemlerden bağımsız çalışmaya olanak tanır ve test sırasında işletim sistemi ortamınızın durumunu ve davranışını güvenli bir şekilde değiştirmenize imkân tanır.

os.path.exists() fikstürü kullanarak monkeypatch işlevini geçersiz kılmak için bir örnek:

import os

def test_os(monkeypatch):
    # Override os.path.exists to always return False
    monkeypatch.setattr('os.path.exists', lambda x: False)
    assert not os.path.exists('/')

Alternatif olarak, nesneye ve özniteliğe doğrudan başvuru ile setattr() yöntemini kullanabilirsiniz:

def test_os(monkeypatch):
    # Specify the object and attribute to override
    monkeypatch.setattr(os.path, 'exists', lambda x: False)
    assert not os.path.exists('/')

monkeypatch fikstür, öznitelikleri ayarlamanın ve geçersiz kılma yöntemlerinin yanı sıra ortam değişkenlerini ayarlayıp silebilir, sözlük değerlerini değiştirebilir ve sistem yollarını değiştirebilir. monkeypatch fikstür her testten sonra değişiklikleri otomatik olarak geri alır, ancak monkeypatch fikstür kullanılırken dikkatli olunmalıdır. Kullanırken dikkatli olmak için bazı nedenler şunlardır:

- Kod netliği ve bakımı: Aşırı kullanmak monkeypatch veya karmaşık yollarla kullanmak testin anlaşılmasını ve bakımını zorlaştırabilir. Test sonuçlarınızı okuduğunuzda, bileşenlerin nasıl normal davranması gerektiği ve test için nasıl değiştirildiği hemen net olmayabilir. - Test geçerliliği: Monkeypatching bazen üretim ortamından çok farklı yapay koşullar altında geçen testlere yol açabilir. Bu, testler sistemin davranışını çok dramatik bir şekilde değiştirdiği için geçebildiğinden dolayı yanlış bir güvenlik duygusu yaratabilir. - Uygulama ayrıntılarına aşırı bağımlılık: Monkeypatching kullanan testler, test ettikleri kodun belirli uygulama ayrıntılarına sıkı bir şekilde bağlı olabilirler. Bu, temel alınan kod tabanında yapılan küçük değişikliklerle bile testleri kısıtlayabilir ve hataya açık hale getirir. - Hata ayıklama karmaşıklığı: Özellikle düzeltme eki uygulama davranışının temel yönlerini değiştiriyorsa, kullanılan monkeypatch testlerde hata ayıklama daha karmaşık olabilir. Bir testin neden başarısız olduğunu anlamak için, test sırasında bileşenlerin nasıl değiştirildiğine daha ayrıntılı bir bakış gerekebilir.

monkeypatch, yalıtılmış ve denetimli test ortamları oluşturmak için güçlü bir araç olsa da, test paketi ve uygulamanın davranışını nasıl etkilediğini net bir şekilde anlamak için uygun şekilde kullanılmalıdır.