pytest के साथ मज़बूत टेस्ट संरचित करें: fixture इंजेक्शन, yield-आधारित टियरडाउन, तालिका-आधारित पैरामीट्राइज़ेशन और व्यापक स्कोप के जाल।
इस पाठ को Kodokon में खोलेंpytest दो मज़बूत विचारों पर टिका है: परंपरा से खोज (test_*.py फ़ाइलें, test_* फ़ंक्शन) और सादा assert, जिसका इंट्रोस्पेक्शन विफलता पर दोनों पक्षों की वास्तविक वैल्यू दिखाता है - अब assertEqual और उसके तीस रूपों को याद रखने की ज़रूरत नहीं। तुरंत जानने लायक दो औज़ार: pytest.raises, यह जाँचने के लिए कि कोई अपवाद वाकई उठाया गया है, और pytest.approx, बाइनरी राउंडिंग से जूझे बिना फ़्लोट की तुलना करने के लिए।
import pytest
def divide(a: float, b: float) -> float:
return a / b
def test_nominal() -> None:
assert divide(8, 4) == 2.0
def test_zero_division() -> None:
with pytest.raises(ZeroDivisionError):
divide(1, 0)
def test_floats() -> None:
assert 0.1 + 0.2 == pytest.approx(0.3)Fixtures pytest का डिपेंडेंसी इंजेक्शन हैं: किसी fixture के नाम वाला एक पैरामीटर घोषित करें, और pytest उसे बनाकर इंजेक्ट कर देता है। yield सेटअप को टियरडाउन से अलग करता है - उसके बाद का कोड तब भी चलता है जब टेस्ट विफल हो जाए। scope पैरामीटर (डिफ़ॉल्ट रूप से function, फिर module, session) ऑब्जेक्ट का जीवनकाल तय करता है। साझा fixtures को किसी conftest.py में रखें: वे पूरे फ़ोल्डर में उपलब्ध हो जाते हैं, बिना एक भी इम्पोर्ट के।
import sqlite3
import pytest
@pytest.fixture
def db():
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE users (name TEXT)")
yield conn
conn.close()
def test_insert(db) -> None:
db.execute("INSERT INTO users VALUES ('Ada')")
query = "SELECT name FROM users"
rows = db.execute(query).fetchall()
assert rows == [("Ada",)]@pytest.mark.parametrize किसी टेस्ट को मामलों की तालिका में बदल देता है: हर टपल एक स्वतंत्र टेस्ट बन जाता है, जिसका अपना नाम होता है और जिसे अलग से फ़िल्टर किया जा सकता है। पैरामीटरों का कार्तीय गुणनफल पाने के लिए कई parametrize डेकोरेटर एक के ऊपर एक लगाएँ। pytest.param(..., id='...') के ज़रिए अपने मामलों को पठनीय id दें - कोई विफलता रिपोर्ट स्रोत फ़ाइल खोले बिना समझ में आनी चाहिए।
import pytest
def slugify(text: str) -> str:
return "-".join(text.lower().split())
@pytest.mark.parametrize(
("raw", "expected"),
[
("Hello World", "hello-world"),
(" Python rocks ", "python-rocks"),
pytest.param("", "", id="empty"),
],
)
def test_slugify(raw: str, expected: str) -> None:
assert slugify(raw) == expectedpytest -x --lf
pytest -k "slugify and not empty"
pytest -q --durations=5yield के बाद रखा गया कोड किसलिए है?pytest --lf कमांड क्या करता है?