2011-12-29 6 views
46

आदेश यकीन है कि मेरी मॉड्यूल से त्रुटि संदेश जानकारीपूर्ण हैं बनाने के लिए, मैं सभी त्रुटि संदेश assertRaises द्वारा पकड़ा देखना चाहेंगे()। आज मैं प्रत्येक assertRaises() के लिए यह करता हूं, लेकिन परीक्षण कोड में उनमें से बहुत सारे हैं, यह बहुत कठिन हो जाता है।कैसे त्रुटि संदेश Python2.7 में assertRaises() unittest में से पकड़ा दिखाने के लिए?

कैसे मैं सभी assertRaises के लिए त्रुटि संदेश() मुद्रित कर सकते हैं? मैंने http://docs.python.org/library/unittest.html पर प्रलेखन का अध्ययन किए बिना यह पता लगाने के लिए प्रलेखन का अध्ययन किया है। क्या मैं किसी भी तरह assertRaises() विधि monkeypatch कर सकते हैं? मैं सभी assertRaises() परीक्षण कोड में लाइनों को बदलने के लिए नहीं पसंद करते हैं, जैसा कि मैंने सबसे अधिक बार परीक्षण कोड मानक तरीका का उपयोग करें।

मुझे लगता है कि इस सवाल का Python unittest: how do I test the argument in an Exceptions?

से संबंधित है यह मैं कैसे यह आज क्या है।

#!/usr/bin/env python 

def fail(): 
    raise ValueError('Misspellled errrorr messageee') 

और परीक्षण कोड: उदाहरण के लिए:

#!/usr/bin/env python 
import unittest 
import failure 

class TestFailureModule(unittest.TestCase): 

    def testFail(self): 
     self.assertRaises(ValueError, failure.fail) 

if __name__ == '__main__': 
    unittest.main() 

त्रुटि संदेश की जाँच करने के लिए, मैं बस() assertRaises में त्रुटि प्रकार उदाहरण IOError के लिए करने के लिए बदल जाते हैं। फिर मैं त्रुटि संदेश देख सकता हूं:

E 
====================================================================== 
ERROR: testFail (__main__.TestFailureModule) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
File "test_failure.py", line 8, in testFail 
    self.assertRaises(IOError, failure.fail) 
    File "/usr/lib/python2.7/unittest/case.py", line 471, in assertRaises 
    callableObj(*args, **kwargs) 
File "/home/jonas/Skrivbord/failure.py", line 4, in fail 
    raise ValueError('Misspellled errrorr messageee') 
ValueError: Misspellled errrorr messageee 

---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

FAILED (errors=1) 

कोई सुझाव? /जोनास

संपादित करें:

रॉबर्ट Rossney से संकेत के साथ मैं समस्या को हल करने में कामयाब रहे। यह मुख्य रूप से वर्तनी त्रुटियों के लिए नहीं है, लेकिन यह सुनिश्चित करने के लिए कि त्रुटि संदेश मॉड्यूल के उपयोगकर्ता के लिए वास्तव में सार्थक हैं। unittest की सामान्य कार्यप्रणाली (यह मैं इसे कैसे समय के सबसे अधिक उपयोग करें) SHOW_ERROR_MESSAGES = झूठी स्थापना द्वारा हासिल की है।

मैं बस assertRaises() विधि, जैसा कि नीचे देखा ओवरराइड। यह आकर्षण की तरह काम करता है!

SHOW_ERROR_MESSAGES = True 

class NonexistantError(Exception): 
    pass 

class ExtendedTestCase(unittest.TestCase): 
    def assertRaises(self, excClass, callableObj, *args, **kwargs): 
     if SHOW_ERROR_MESSAGES: 
      excClass = NonexistantError 
     try: 
      unittest.TestCase.assertRaises(self, excClass, callableObj, *args, **kwargs) 
     except: 
      print '\n ' + repr(sys.exc_info()[1]) 

जिसके परिणामस्वरूप उत्पादन का एक अंश:

testNotIntegerInput (__main__.TestCheckRegisteraddress) ... 
    TypeError('The registeraddress must be an integer. Given: 1.0',) 

    TypeError("The registeraddress must be an integer. Given: '1'",) 

    TypeError('The registeraddress must be an integer. Given: [1]',) 

    TypeError('The registeraddress must be an integer. Given: None',) 
ok 
testCorrectNumberOfBytes (__main__.TestCheckResponseNumberOfBytes) ... ok 
testInconsistentLimits (__main__.TestCheckNumerical) ... 
    ValueError('The maxvalue must not be smaller than minvalue. Given: 45 and 47, respectively.',) 

    ValueError('The maxvalue must not be smaller than minvalue. Given: 45.0 and 47.0, respectively.',) 
ok 
testWrongValues (__main__.TestCheckRegisteraddress) ... 
    ValueError('The registeraddress is too small: -1, but minimum value is 0.',) 

    ValueError('The registeraddress is too large: 65536, but maximum value is 65535.',) 
ok 
testTooShortString (__main__.TestCheckResponseWriteData) ... 
    ValueError("The payload is too short: 2, but minimum value is 4. Given: '\\x00X'",) 

    ValueError("The payload is too short: 0, but minimum value is 4. Given: ''",) 

    ValueError("The writedata is too short: 1, but minimum value is 2. Given: 'X'",) 

    ValueError("The writedata is too short: 0, but minimum value is 2. Given: ''",) 
ok 
testKnownValues (__main__.TestCreateBitPattern) ... ok 
testNotIntegerInput (__main__.TestCheckSlaveaddress) ... 
    TypeError('The slaveaddress must be an integer. Given: 1.0',) 

    TypeError("The slaveaddress must be an integer. Given: '1'",) 

    TypeError('The slaveaddress must be an integer. Given: [1]',) 

    TypeError('The slaveaddress must be an integer. Given: None',) 
ok 
+4

आप तर्क जांच करने की आवश्यकता है, तो assertRaises उपयोग करने के लिए क्यों जारी रखें? क्यों न केवल अपवाद को पकड़ें और 'try' और' वगैरह 'का उपयोग करके इसकी जांच करें? –

उत्तर

34

आउट ऑफ द बॉक्स unittest ऐसा नहीं करती है। यह कुछ आप अक्सर क्या करना चाहते है, तो आप कुछ इस तरह की कोशिश कर सकते हैं:

class ExtendedTestCase(unittest.TestCase): 

    def assertRaisesWithMessage(self, msg, func, *args, **kwargs): 
    try: 
     func(*args, **kwargs) 
     self.assertFail() 
    except Exception as inst: 
     self.assertEqual(inst.message, msg) 

ExtendedTestCase बजाय unittest.TestCase से अपने इकाई परीक्षण वर्गों प्राप्त।

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

+11

+1 "एक डेवलपर जो अपने कोड में शब्दों को गलत तरीके से याद करता है, उन्हें भी उनके परीक्षण मामलों में गलत तरीके से मिस जाएगा।" – Johnsyweb

+7

मेरे लिए, यह देखने के लिए परीक्षण कर रहे हैं कि _specific_ त्रुटि हो रही है, लेकिन यह परीक्षण अनपेक्षित साइड इफेक्ट्स के कारण 'पास' कर सकता है। जैसे आपके द्वारा अपेक्षित त्रुटि को उठाया नहीं गया था, लेकिन एक ही त्रुटि प्रकार कहीं और उठाया गया है, इस प्रकार परीक्षण को संतुष्ट करता है। परीक्षण पास होता है, कोड खराब हो जाता है। त्रुटियों के लिए वही सौदा जो आप जिस त्रुटि को खोज रहे हैं उसे उप-वर्गीकृत करें - यदि आपका परीक्षण बहुत सामान्य है, तो आप ऐसा कुछ हासिल कर सकते हैं जिसकी आप अपेक्षा नहीं करते हैं। –

+1

आप का उपयोग करना चाहिए '' inst.args [0] '' बजाय '' inst.message'' अजगर 2 और अजगर 3 – oblalex

71

मैं एक बार @Robert Rossney द्वारा ऊपर दिए गए सबसे उत्कृष्ट जवाब को प्राथमिकता दी।आजकल, मैं बहुत की तरह एक संदर्भ प्रबंधक (unittest2 में एक नई क्षमता) के रूप में assertRaises का उपयोग करना पसंद:

with self.assertRaises(TypeError) as cm: 
    failure.fail() 
self.assertEqual(
    'The registeraddress must be an integer. Given: 1.0', 
    str(cm.exception) 
) 
+0

एनबी। पाइथन 2.7 में 'unittest' से संदर्भ प्रबंधक के रूप में assertRaises का उपयोग किया जा सकता है। पायथन के पिछले संस्करणों के लिए unittest2 बैकपोर्ट्स विशेषताएं। http://docs.python.org/2/library/unittest.html#unittest.TestCase.assertRaises – powlo

+0

क्या होगा यदि कोड "के साथ" भाग में विफल रहता है .... मेरे मामले में, भाग के साथ विफल रहता है .. इसलिए मैं एक संदेश दिखाना चाहता हूं .. जैसा कि हम अन्य सादे आवेषणों के लिए कर सकते हैं जैसे self.assertEqual (cm.exception.faultCode, 101001, 'दोष कोड अपेक्षित गलती कोड% d'% 101001 से मेल नहीं खाता) –

+0

@रिंदमरोचौधरी, मुझे खेद है, लेकिन मैंने कुछ समय में किसी भी पायथन को कोड नहीं किया है, इसलिए मुझे आपके प्रश्न का उत्तर नहीं पता है। शुभकामनाएँ। शायद, यहां पर अन्य लोगों में से एक आपके प्रश्न का बेहतर जवाब दे सकता है। सौभाग्य। – mkelley33

34

आप देख रहे हैं assertRaisesRegexp, जो अजगर 2.7 के बाद से उपलब्ध है के लिए।

self.assertRaisesRegexp(ValueError, 'invalid literal for.*XYZ$', int, 'XYZ') 

या: डॉक्स से

with self.assertRaisesRegexp(ValueError, 'literal'): 
    int('XYZ') 
+0

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

4

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

तो, मैं रॉबर्ट के Rossney जवाब में सुधार करना चाहते हैं:

class TestCaseMixin(object): 

    def assertRaisesWithMessage(self, exception_type, message, func, *args, **kwargs): 
     try: 
      func(*args, **kwargs) 
     except exception_type as e: 
      self.assertEqual(e.args[0], message) 
     else: 
      self.fail('"{0}" was expected to throw "{1}" exception' 
         .format(func.__name__, exception_type.__name__)) 

कुंजी अंतर हैं:

  1. हम अपवाद के प्रकार का परीक्षण करें।
  2. हम इस कोड को पायथन 2 और पायथन 3 पर चला सकते हैं (हम e.args[0] पर कॉल करते हैं क्योंकि Py3 में त्रुटियों में message विशेषता नहीं है)।
8

आपको त्रुटि संदेश वास्तव में कुछ मेल खाते हैं चाहते हैं:

with self.assertRaises(ValueError) as error: 
    do_something() 
self.assertEqual(error.exception.message, 'error message') 
संबंधित मुद्दे