Tutorial Material

Pytest Fixtures haqida

Share to
Pytest Fixtures

Oldingi testlash darsida pytest yordamida asosiy testlarni qanday yozishni o'rgandik. Haqiqiy loyihalarda esa testlar ishlashidan oldin ma'lum bir holatni tayyorlash (masalan, ma'lumotlar bazasiga ulanish yoki soxta ma'lumotlar yaratish) va ish tugagach uni tozalash kerak bo'ladi. pytestda bu fixture'lar yordamida qulay bajariladi.

Fixture nima?

Fixture — pytest test funksiyalaringiz ishlashidan oldin (va kerak bo'lsa, keyin) ishga tushiradigan funksiya. Fixture'ni so'rash uchun uning nomini test funksiyangizga argument sifatida qo'shasiz.

# non-runnable: requires pytest
import pytest

@pytest.fixture
def sample_user():
    return {"id": 1, "username": "jane_doe", "role": "admin"}

def test_user_is_admin(sample_user):
    # pytest sample_user funksiyasi qaytargan qiymatni shu yerga avtomatik yuboradi
    assert sample_user["role"] == "admin"

Setup va Teardown (Yield)

Fixture'lar faqat ma'lumot qaytarish uchun emas; ular resurslarni boshqarish uchun ham mo'ljallangan. Agar return o'rniga yield kalit so'zidan foydalansangiz, yielddan oldingi kod tayyorlash (setup), yielddan keyingi kod esa test tugagandan so'ng ishlaydigan tozalash (teardown) bo'ladi.

# non-runnable: requires pytest
import pytest

@pytest.fixture
def database_connection():
    # Tayyorlash (Setup)
    db = connect_to_database()
    print("Database connected")
    
    yield db  # Test aynan shu yerda bajariladi
    
    # Tozalash (Teardown)
    db.close()
    print("Database connection closed")

def test_insert_user(database_connection):
    database_connection.insert("dummy user")
    assert database_connection.count() == 1

Fixture Scope'lari

Standart holatda fixture har bir test funksiyasi uchun bir marta ishlaydi (scope="function"). Agar fixture'ni ishga tushirish qimmatga tushsa (masalan, docker konteynerini ishga tushirish), uni kamroq tez-tez ishlashi uchun qamrovini (scope) o'zgartirishingiz mumkin.

# non-runnable: requires pytest
@pytest.fixture(scope="session")
def expensive_api_client():
    # Buni 100 ta test so'rasa ham, faqat bir marta bajariladi
    client = ExpensiveAPIClient()
    client.authenticate()
    yield client
    client.logout()

Bir nechta Fixture'dan foydalanish

Testlar bir nechta fixture'ni so'rashi mumkin.

# non-runnable: requires pytest
@pytest.fixture
def user():
    return User(name="Alice")

@pytest.fixture
def shopping_cart():
    return Cart()

def test_add_to_cart(user, shopping_cart):
    shopping_cart.add(user, "Laptop")
    assert "Laptop" in shopping_cart.items

conftest.py fayli

Agar fixture'larni har bir test fayliga qo'lda import qilmasdan bir nechta test faylida ishlatmoqchi bo'lsangiz, ularni test papkangizning ildizida joylashgan conftest.py faylida aniqlang. Pytest uni avtomatik topadi.

Fixture'larni parametrlash

params berib, fixture'ni ro'yxatdagi har bir qiymat uchun bir martadan ishga tushirish mumkin. Fixture'dan foydalanadigan har bir test har bir parametr uchun bir marta ishlaydi, shuning uchun testni takrorlamasdan ko'plab kirishlarni qamrab olasiz. Joriy qiymat request.param orqali mavjud bo'ladi.

# non-runnable: requires pytest
import pytest

@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def database(request):
    return connect(request.param)

def test_connection(database):
    # Bu test uch marta ishlaydi — har bir database backend uchun
    assert database.is_connected()

Foydali built-in fixture'lar

Pytest oldindan tayyor fixture'lar bilan keladi; ularni alohida aniqlamasdan so'rashingiz mumkin:

Fixture Vazifasi
tmp_path Har bir test uchun noyob vaqtinchalik papka (Path).
monkeypatch Atributlar, env o'zgaruvchilari yoki dict elementlarini xavfsiz patch qilish.
capsys stdout / stderr'ga yozilgan matnni ushlash.
caplog Test davomida chiqarilgan log yozuvlarini ushlash.
# non-runnable: requires pytest
def test_writes_file(tmp_path):
    target = tmp_path / "out.txt"
    target.write_text("hello")
    assert target.read_text() == "hello"

def test_uses_env(monkeypatch):
    monkeypatch.setenv("API_KEY", "test-key")
    assert get_api_key() == "test-key"

Xulosa

Fixture'lar pytestning asosiy imkoniyatlaridan biridir. Ular qayta foydalanishni osonlashtiradi, tayyorlash mantig'ini test mantig'idan ajratadi va yield namunasi yordamida tashqi resurslarni xavfsiz boshqarishga yordam beradi.