Python Language
py.test
खोज…
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 स्थिरता दस्तावेज़ और आधिकारिक उपज स्थिरता दस्तावेज़ देखें