पायथन कई रिटर्न मूल्यों का मजाक उड़ाता है


168

मैं अजगर mock.patch का उपयोग कर रहा हूं और प्रत्येक कॉल के लिए वापसी मूल्य बदलना चाहूंगा। यहां चेतावनी दी गई है: पैच किए जा रहे फ़ंक्शन में कोई इनपुट नहीं है, इसलिए मैं इनपुट के आधार पर रिटर्न मान नहीं बदल सकता।

यहाँ संदर्भ के लिए मेरा कोड है।

def get_boolean_response():
    response = io.prompt('y/n').lower()
    while response not in ('y', 'n', 'yes', 'no'):
        io.echo('Not a valid input. Try again'])
        response = io.prompt('y/n').lower()

    return response in ('y', 'yes')

मेरा टेस्ट कोड:

@mock.patch('io')
def test_get_boolean_response(self, mock_io):
    #setup
    mock_io.prompt.return_value = ['x','y']
    result = operations.get_boolean_response()

    #test
    self.assertTrue(result)
    self.assertEqual(mock_io.prompt.call_count, 2)

io.promptकेवल एक प्लेटफ़ॉर्म स्वतंत्र (अजगर 2 और 3) "इनपुट" संस्करण है। इसलिए अंततः मैं यूजर्स के इनपुट का मजाक बनाने की कोशिश कर रहा हूं। मैंने वापसी मूल्य के लिए एक सूची का उपयोग करने की कोशिश की है, लेकिन यह काम करने के लिए सीवन नहीं करता है।

आप देख सकते हैं कि यदि रिटर्न वैल्यू कुछ अमान्य है, तो मुझे यहाँ एक अनंत लूप मिलेगा। इसलिए मुझे अंततः वापसी मूल्य को बदलने का एक तरीका चाहिए, ताकि मेरा परीक्षण वास्तव में समाप्त हो जाए।

(इस सवाल का जवाब देने का एक और संभावित तरीका यह समझाने के लिए हो सकता है कि मैं यूनिट-टेस्ट में उपयोगकर्ता इनपुट की नकल कैसे कर सकता हूं)


मुख्य रूप से इस सवाल का एक हिस्सा नहीं है क्योंकि मैं आदानों को अलग करने की क्षमता नहीं है।

इस प्रश्न पर उत्तर की टिप्पणियों में से एक समान लाइनों के साथ है, लेकिन कोई उत्तर / टिप्पणी प्रदान नहीं की गई है।


3
response is not 'y' or 'n' or 'yes' or 'no'में नहीं कर रही है तुम्हें क्या लगता है यह करता है। देखें कि मैं एक चर को कई मानों के खिलाफ कैसे जांच सकता हूं? और आप चाहिए नहीं का उपयोग isस्ट्रिंग मूल्यों, उपयोग तुलना करने के लिए ==तुलना करने के लिए मूल्यों , नहीं वस्तु पहचान।
मार्टिन पीटर्स

यहां भी सावधानी बरतें। ऐसा लगता है कि आप isस्ट्रिंग शाब्दिकों की तुलना करने के लिए उपयोग करने का प्रयास कर रहे हैं । ऐसा मत करो। तथ्य यह है कि यह काम करता है (कभी-कभी) केवल CPython में एक कार्यान्वयन विवरण है। इसके अलावा, response is not 'y' or 'n' or 'yes' or 'no'शायद वह नहीं कर रहा है जो आपको लगता है कि यह है ...
mgilson

जवाबों:


300

तुम एक प्रदान कर सकते हैं iterable करने side_effect, और नकली अनुक्रम में हर बार यह कहा जाता है अगले मान प्रदान करेगा:

>>> from unittest.mock import Mock
>>> m = Mock()
>>> m.side_effect = ['foo', 'bar', 'baz']
>>> m()
'foo'
>>> m()
'bar'
>>> m()
'baz'

Mock()दस्तावेज का उद्धरण :

यदि side_effect एक पुनरावृत्त है, तो मॉक पर प्रत्येक कॉल पुनरावृत्त से अगला मान लौटाएगा।

एक तरफ के रूप में, परीक्षण काम नहींresponse is not 'y' or 'n' or 'yes' or 'no' करेगा ; आप पूछ रहे हैं कि क्या अभिव्यक्ति सच है, या सच है (हमेशा मामला, एक गैर-रिक्त स्ट्रिंग हमेशा सच होती है), आदि। ऑपरेटरों के दोनों ओर के विभिन्न भाव स्वतंत्र हैं । देखें कि मैं एक चर को कई मानों के खिलाफ कैसे जांच सकता हूं?(response is not 'y')'y'or

आपको एक स्ट्रिंग के खिलाफ परीक्षण करने के लिए भी उपयोग नहीं करना चाहिए is। CPython दुभाषिया कुछ परिस्थितियों में स्ट्रिंग ऑब्जेक्ट्स का पुन: उपयोग कर सकता है , लेकिन यह वह व्यवहार नहीं है जिसे आपको गिनना चाहिए।

जैसे, उपयोग करें:

response not in ('y', 'n', 'yes', 'no')

बजाय; यह निर्धारित करने के लिए समानता परीक्षण ( ==) का उपयोग करेगा कि क्या responseएक ही सामग्री (मूल्य) के साथ एक स्ट्रिंग को संदर्भित करता है।

वही लागू होता है response == 'y' or 'yes'; response in ('y', 'yes')इसके बजाय उपयोग करें ।


क्या मानक के साथ ऐसा करने का कोई तरीका है mock? क्या मैजिकमॉक के साथ पैच का उपयोग करने का एक तरीका है जैसे मैं मानक नकली के साथ कर रहा हूं?
निक हम्रीच

@Humdinger: यह स्टारडर्ड Mockक्लास की एक विशेषता है ।
मार्टिन पीटर्स

17
एक सूची सौंपना केवल अजगर 3 के साथ काम करने के लिए प्रकट होता है। अजगर 2.7 के साथ परीक्षण मुझे इसके बजाय एक पुनरावृत्ति ( m.side_effect = iter(['foo', 'bar', 'baz'])) का उपयोग करने की आवश्यकता है ।
user686249

1
@ user686249: मैं वास्तव में इसे पुन: पेश कर सकता हूं, क्योंकि एक विधि से कल्पना एक lambda(एक फ़ंक्शन) का उत्पादन करती है , न कि ए MagicMock। एक फ़ंक्शन ऑब्जेक्ट में गुण नहीं हो सकते हैं, इसलिए side_effectविशेषता को चलने योग्य होना चाहिए। आपको हालांकि इस तरह की विधि का अनुमान नहीं लगाना चाहिए। बेहतर उपयोग mock.patch.object(requests.Session, 'post'); एक पैच ऑब्जेक्ट में यह परिणाम है कि विधि पर ठीक से ऑटो-चश्मा, औरside_effect ठीक से समर्थन करता है।
मार्टिन पीटर्स

3
@ JoeMjr2: जब इटरेटर समाप्त हो जाता है, StopIterationउठाया जाता है। आप किसी भी पुनरावृत्त का उपयोग कर सकते हैं, इसलिए आप एक बार itertools.chain(['Foo'], itertools.repeat('Bar'))उत्पादन करने के लिए उपयोग कर सकते हैं Foo, फिर हमेशा के लिए उत्पादन कर सकते हैं Bar
मार्टिन पीटर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.