खोज…


Py.test की स्थापना

py.test कई तीसरे पक्ष के परीक्षण पुस्तकालयों में से एक है जो पायथन के लिए उपलब्ध हैं। इसके साथ pip का उपयोग करके स्थापित किया जा सकता है

pip install pytest

परीक्षण करने के लिए कोड

कहते हैं कि हम एक अतिरिक्त फ़ंक्शन का परीक्षण कर रहे हैं projectroot/module/code.py :

# projectroot/module/code.py
def add(a, b):
    return a + b

परीक्षण कोड

हम projectroot/tests/test_code.py में एक परीक्षण फ़ाइल projectroot/tests/test_code.py । फ़ाइल को परीक्षण फ़ाइल के रूप में पहचाने test_ लिए test_ से शुरू होना चाहिए

# projectroot/tests/test_code.py
from module import code


def test_add():
    assert code.add(1, 2) == 3

टेस्ट चल रहा है

projectroot हम बस py.test चलाते हैं:

# ensure we have the modules
$ touch tests/__init__.py
$ touch module/__init__.py
$ py.test
================================================== test session starts ===================================================
platform darwin -- Python 2.7.10, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /projectroot, inifile:
collected 1 items

tests/test_code.py .

================================================ 1 passed in 0.01 seconds ================================================

फेलिंग टेस्ट

एक असफल परीक्षण, जो गलत हुआ, उसके लिए उपयोगी आउटपुट प्रदान करेगा:

# projectroot/tests/test_code.py
from module import code


def test_add__failing():
    assert code.add(10, 11) == 33

परिणाम:

$ py.test
================================================== test session starts ===================================================
platform darwin -- Python 2.7.10, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /projectroot, inifile:
collected 1 items

tests/test_code.py F

======================================================== FAILURES ========================================================
___________________________________________________ test_add__failing ____________________________________________________

    def test_add__failing():
>       assert code.add(10, 11) == 33
E       assert 21 == 33
E        +  where 21 = <function add at 0x105d4d6e0>(10, 11)
E        +    where <function add at 0x105d4d6e0> = code.add

tests/test_code.py:5: AssertionError
================================================ 1 failed in 0.01 seconds ================================================

टेस्ट फिक्स्चर के लिए परिचय

अधिक जटिल परीक्षणों को कभी-कभी कोड को चलाने से पहले आपके द्वारा परीक्षण किए जाने की आवश्यकता होती है। परीक्षण फ़ंक्शन में ही ऐसा करना संभव है, लेकिन फिर आप बड़े परीक्षण कार्यों को समाप्त कर देते हैं ताकि यह बताना मुश्किल हो जाए कि सेटअप कहाँ रुकता है और परीक्षण शुरू होता है। आप अपने विभिन्न परीक्षण कार्यों के बीच बहुत सारे डुप्लिकेट सेटअप कोड भी प्राप्त कर सकते हैं।

हमारी कोड फ़ाइल:

# projectroot/module/stuff.py
class Stuff(object):
    def prep(self):
        self.foo = 1
        self.bar = 2

हमारी परीक्षण फ़ाइल:

# projectroot/tests/test_stuff.py
import pytest
from module import stuff


def test_foo_updates():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

ये बहुत सरल उदाहरण हैं, लेकिन अगर हमारे Stuff ऑब्जेक्ट को बहुत अधिक सेटअप की आवश्यकता होती है, तो यह अस्पष्ट होगा। हम देखते हैं कि हमारे परीक्षण मामलों के बीच कुछ डुप्लिकेट कोड है, इसलिए पहले एक अलग फ़ंक्शन में इसे रिफ्लेक्टर करते हैं।

# projectroot/tests/test_stuff.py
import pytest
from module import stuff


def get_prepped_stuff():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    return my_stuff


def test_foo_updates():
    my_stuff = get_prepped_stuff()
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates():
    my_stuff = get_prepped_stuff()
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

यह बेहतर लग रहा है, लेकिन हमारे पास अभी भी my_stuff = get_prepped_stuff() कॉल हमारे परीक्षण कार्यों को अव्यवस्थित कर रहा है।

बचाव के लिए py.test जुड़नार!

जुड़नार परीक्षण सेटअप कार्यों के बहुत अधिक शक्तिशाली और लचीले संस्करण हैं। वे हमारे यहां लाभ उठाने की तुलना में बहुत अधिक कर सकते हैं, लेकिन हम इसे एक बार में एक कदम उठाएंगे।

सबसे पहले हम get_prepped_stuff को prepped_stuff नामक एक prepped_stuff । आप अपने जुड़नार का नाम क्रिया के बजाय संज्ञाओं के साथ रखना चाहते हैं क्योंकि जुड़नार कैसे समाप्त हो जाएंगे इसका उपयोग बाद में स्वयं परीक्षण कार्यों में किया जा रहा है। @pytest.fixture इंगित करता है कि इस विशिष्ट फ़ंक्शन को एक नियमित फ़ंक्शन के बजाय एक स्थिरता के रूप में नियंत्रित किया जाना चाहिए।

@pytest.fixture
def prepped_stuff():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    return my_stuff

अब हमें परीक्षण कार्यों को अद्यतन करना चाहिए ताकि वे स्थिरता का उपयोग करें। यह उनकी परिभाषा के लिए एक पैरामीटर जोड़कर किया जाता है जो कि स्थिरता नाम से बिल्कुल मेल खाता है। जब py.test निष्पादित होता है, तो यह परीक्षण चलाने से पहले स्थिरता को चलाएगा, फिर उस पैरामीटर के माध्यम से परीक्षण फ़ंक्शन में स्थिरता के रिटर्न मान को पास करें। (ध्यान दें कि जुड़नार को एक मूल्य वापस करने की आवश्यकता नहीं है ; वे इसके बजाय अन्य सेटअप चीजें कर सकते हैं, जैसे एक बाहरी संसाधन को कॉल करना, फाइल सिस्टम पर चीजों को व्यवस्थित करना, एक डेटाबेस में मान डालना, जो भी सेटअप के लिए परीक्षण की आवश्यकता है)

def test_foo_updates(prepped_stuff):
    my_stuff = prepped_stuff
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates(prepped_stuff):
    my_stuff = prepped_stuff
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

अब आप देख सकते हैं कि हमने इसका नाम संज्ञा से क्यों रखा। लेकिन my_stuff = prepped_stuff लाइन बहुत ज्यादा बेकार है, तो चलो सीधे बजाय prepped_stuff उपयोग करें।

def test_foo_updates(prepped_stuff):
    assert 1 == prepped_stuff.foo
    prepped_stuff.foo = 30000
    assert prepped_stuff.foo == 30000


def test_bar_updates(prepped_stuff):
    assert 2 == prepped_stuff.bar
    prepped_stuff.bar = 42
    assert 42 == prepped_stuff.bar

अब हम जुड़नार का उपयोग कर रहे हैं! हम स्थिरता के दायरे को बदलकर आगे बढ़ सकते हैं (इसलिए यह केवल एक बार परीक्षण मॉड्यूल या टेस्ट सूट निष्पादन सत्र के बजाय एक बार परीक्षण समारोह के अनुसार) चलता है, अन्य जुड़नार का उपयोग करने वाले जुड़नार का निर्माण, स्थिरता तय करता है (ताकि स्थिरता और सभी उस स्थिरता का उपयोग करने वाले परीक्षण कई बार चलाए जाते हैं, एक बार तयशुदा को दिए गए प्रत्येक पैरामीटर के लिए), जुड़नार जो मॉड्यूल से मूल्यों को पढ़ते हैं जो उन्हें कॉल करते हैं ... जैसा कि पहले उल्लेख किया गया है, जुड़नार में एक सामान्य सेटअप फ़ंक्शन की तुलना में बहुत अधिक शक्ति और लचीलापन होता है।

परीक्षण किए जाने के बाद सफाई।

मान लीजिए कि हमारा कोड बड़ा हो गया है और हमारी स्टफ ऑब्जेक्ट को अब विशेष सफाई की आवश्यकता है।

# projectroot/module/stuff.py
class Stuff(object):
def prep(self):
    self.foo = 1
    self.bar = 2

def finish(self):
    self.foo = 0
    self.bar = 0

हम प्रत्येक परीक्षण फ़ंक्शन के निचले भाग में सफाई को कॉल करने के लिए कुछ कोड जोड़ सकते हैं, लेकिन जुड़नार ऐसा करने का एक बेहतर तरीका प्रदान करते हैं। यदि आप किसी फ़ंक्शन को फ़िक्चर में जोड़ते हैं और इसे अंतिम रूप से पंजीकृत करते हैं, तो फ़ाइल्चर का उपयोग करके परीक्षण के बाद फ़ाइनलाइज़र फ़ंक्शन में कोड को कॉल किया जाएगा। यदि फिक्सेचर का दायरा एकल फ़ंक्शन (जैसे मॉड्यूल या सत्र) से बड़ा है, तो अंतिम रूप से सभी परीक्षण दायरे में आने के बाद निष्पादित किए जाएंगे, इसलिए मॉड्यूल के चलने के बाद या संपूर्ण परीक्षण रनिंग सत्र के अंत में ।

@pytest.fixture
def prepped_stuff(request):  # we need to pass in the request to use finalizers
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    def fin():  # finalizer function
        # do all the cleanup here
        my_stuff.finish()
    request.addfinalizer(fin)  # register fin() as a finalizer
    # you can do more setup here if you really want to
    return my_stuff

किसी फ़ंक्शन के अंदर फ़ाइनलज़र फ़ंक्शन का उपयोग करना पहली नज़र में समझना थोड़ा कठिन हो सकता है, खासकर जब आपके पास अधिक जटिल जुड़नार हों। आप इसके बजाय अधिक मानव पठनीय निष्पादन प्रवाह के साथ एक ही काम करने के लिए एक उपज स्थिरता का उपयोग कर सकते हैं। एकमात्र वास्तविक अंतर यह है कि हम return का उपयोग करने के बजाय, उस स्थिरता के हिस्से पर एक yield का उपयोग करते return जहां सेटअप किया जाता है और नियंत्रण को एक परीक्षण फ़ंक्शन पर जाना चाहिए, फिर yield के बाद सभी सफाई कोड जोड़ें। हम इसे एक yield_fixture रूप में भी सजाते हैं ताकि py.test जानता है कि इसे कैसे संभालना है।

@pytest.yield_fixture
def prepped_stuff():  # it doesn't need request now!
    # do setup
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    # setup is done, pass control to the test functions
    yield my_stuff
    # do cleanup 
    my_stuff.finish()

और वह अंत में टेस्ट फिक्स्चर का परिचय देता है!

अधिक जानकारी के लिए, आधिकारिक py.test स्थिरता दस्तावेज़ और आधिकारिक उपज स्थिरता दस्तावेज़ देखें



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow