2011-03-01 9 views
10

पर मौजूद होने के लिए मैं अपने परीक्षण के लिए एक पायथन mock library का उपयोग शुरू करने का उपयोग कर रहा हूं। मैं एक मॉड्यूल का नकल करना चाहता हूं जो वास्तव में इसे आयात किए बिना परीक्षण के तहत मॉड्यूल के नामस्थान में आयात किया गया है या यह आवश्यक है कि यह पहले मौजूद हो (यानी एक आयातक फेंकना)।पायथन: इसे आयात किए बिना मॉड्यूल को मॉक करें या इसे

मान लीजिए निम्नलिखित कोड मौजूद है:

foo.py

import helpers 
def foo_func(): 
    return helpers.helper_func() 

लक्ष्य foo_func परीक्षण करने के लिए() जब 'helpers.py' कहीं भी मौजूद नहीं है, और यह मौजूद है, तो कार्य जैसे कि यह नहीं करता है।

पहले सुपर शांत @patch डेकोरेटर का उपयोग करके देखें,:

from mock import patch, sentinel 
import foo 
@patch("foo.helpers") 
def foo_test(mock): 
    mock.helper_func.return_value = sentinel.foobar 
    assert foo.foo_func() == sentinel.foobar 

यह काम करता है "सहायकों" मॉड्यूल आयात किया जा सकता। यदि यह अस्तित्व में नहीं है, तो मुझे एक आयात त्रुटि मिलती है।

पैच, बिना डेकोरेटर के साथ अगला प्रयास:

from mock import patch, sentinel, Mock 
import foo 
helpers_mock = patch("foo.helpers") 
helpers_mock.start() 

def foo_test(): 
    helpers_mock.helper_func = Mock('helper_func') 
    helpers_mock.helper_func.return_value = sentinel.foobar 
    assert foo.foo_func() == sentinel.foobar 

फिर, यह अगर "सहायकों" याद आ रही है काम नहीं करता है ... और, यदि वह मौजूद है, दावे विफल रहता है। वास्तव में यकीन नहीं है कि ऐसा क्यों होता है।

तीसरे प्रयास, मौजूदा समाधान:

import sys 
helpers_mock = Mock(name="helpers_mock", spec=['helper_func']) 
helpers_mock.__name__ = 'helpers' 
sys.modules['helpers'] = helpers_mock 
import foo 
def foo_test(): 
    helpers_mock.helper_func.return_value = sentinel.foobar 
    assert foo.foo_func() == sentinel.foobar 

यह परीक्षण किया जाए या नहीं "helpers.py" मौजूद है की परवाह किए बिना गुजरता है।

क्या यह इस लक्ष्य को पूरा करने का सबसे अच्छा तरीका है? क्या मैं जिस मॉकिंग लाइब्रेरी का उपयोग कर रहा हूं वह इसका विकल्प प्रदान करता है? मैं यह और कैसे कर सकता हूं?

+0

जबकि मैं सभी को बेकार करने के लिए हूं, मुझे लगता है कि इस मामले में आप भाषा की एक विशेषता का परीक्षण कर रहे हैं और आपके कोड का एक उपयोगी कार्य नहीं है। आप अपने आयात को foo.py में भी ठीक कर सकते हैं ताकि इस बंदर पैचिंग में से कुछ आयात गार्ड के साथ अनावश्यक है (उदाहरण: कोशिश करें: आयात करने वालों को आयात करने के लिए आयात करें: मददगार = नंगे आयात के बजाय foo.py में कोई भी नहीं)। मेरा मतलब है कि अभी foo.py में मदद नहीं की गई है ताकि मददगार गायब हो जाएं और इससे आपके परीक्षणों को बहुत सरल बनाना चाहिए। – stderr

+0

मुझे वास्तव में आयात गार्ड विचार पसंद है, यह बहुत सारे मुद्दों को हल करता है। यदि मैं आपके द्वारा सुझाए गए आयात गार्ड का उपयोग करता हूं, तो मैं पहले उदाहरण (@ पैच सजावट) का उपयोग करने में सक्षम हूं। धन्यवाद! –

उत्तर

3

आप एक मॉक के बिंदु को याद कर रहे हैं। जब आप किसी विशेष इंटरफ़ेस के साथ ऑब्जेक्ट चाहते हैं, तो आप उन्हें बनाना चाहते हैं, भले ही इसे कार्यान्वित किया जाए।

आप जो कर रहे हैं वह पाइथन के मॉड्यूल सिस्टम को फिर से कार्यान्वित करने का प्रयास कर रहा है, साथ ही यह बूट करने के लिए वैश्विक चर के एक बहुत ही भयानक दुर्व्यवहार है।

फू मॉड्यूल बनाने के बजाय, फू क्लास बनाएं, और कन्स्ट्रक्टर में हेल्पर्स में पास करें।

class Foo(object): 
    def __init__(self, helpers): 
     self.helpers = helpers 

# then, instead of import foo: 
foo = Foo(mock_helpers) 

यहां तक ​​कि अगर असली "सहायकों" वास्तव में एक मॉड्यूल होने जा रहा है, वहाँ कोई कारण नहीं तुम sys.modules साथ खिलवाड़ करने और अपने परीक्षण में import के माध्यम से इसे स्थापित करने करने की आवश्यकता है।

और अगर foo एक मॉड्यूल हो गया है, वह भी ठीक है, लेकिन आप इसे इस तरह से कार्य करें: मानक पुस्तकालय काम के

# foo.py 
class Foo(object): 
    pass # same code as before, plus foo_func 

try: 
    import whatever 
    _singleton = Foo(whatever) 
except ImportError: 
    _singleton = Foo(something_else) 

def foo_func(): 
    return _singleton.foo_func() 

बड़े हिस्से में इस तरह। सिंगलटन जैसी मॉड्यूल को परिभाषित करने के लिए यह काफी मानक है।

+1

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

संबंधित मुद्दे