2016-05-10 4 views
8

मैंने पाइथन यूनिट परीक्षण की setUp विधि में assert के उपयोग पर कुछ विवादित सलाह पढ़ी है। परीक्षण में असफल होने में मुझे नुकसान दिखाई नहीं दे रहा है यदि परीक्षण की पूर्व शर्त विफल रहता है।सेटअप विधि में पाइथन में एक त्रुटि में त्रुटि की रिपोर्ट करने का सही तरीका क्या है?

उदाहरण के लिए:

import unittest 

class MyProcessor(): 
    """ 
    This is the class under test 
    """ 

    def __init__(self): 
     pass 

    def ProcessData(self, content): 
     return ['some','processed','data','from','content'] # Imagine this could actually pass 

class Test_test2(unittest.TestCase): 

    def LoadContentFromTestFile(self): 
     return None # Imagine this is actually doing something that could pass. 

    def setUp(self): 
     self.content = self.LoadContentFromTestFile() 
     self.assertIsNotNone(self.content, "Failed to load test data") 
     self.processor = MyProcessor() 

    def test_ProcessData(self): 
     results = self.processor.ProcessData(self.content) 
     self.assertGreater(results, 0, "No results returned") 

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

यह लगता है एक उचित बात मेरे लिए क्या करने के लिए की तरह अर्थात यकीन है कि परीक्षण चलाने के लिए सक्षम है या नहीं। जब इस स्थापना स्थिति के कारण विफल रहता है हम पाते हैं:

F 
====================================================================== 
FAIL: test_ProcessData (__main__.Test_test2) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "C:\Projects\Experiments\test2.py", line 21, in setUp 
    self.assertIsNotNone(self.content, "Failed to load test data") 
AssertionError: unexpectedly None : Failed to load test data 

---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

FAILED (failures=1) 

उत्तर

9

setUp के प्रयोजन के Boilerplate code जो परीक्षण के बीच पैदा करता है कम करने के लिए है व्यवस्था के चरण के दौरान परीक्षण कक्षा में

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

।उपर्युक्त अनुच्छेदों के आधार पर आपको अपने setUp विधि में कुछ भी जोर नहीं देना चाहिए।

जैसा कि पहले उल्लेख किया गया है; यदि आप परीक्षण पूर्व शर्त नहीं बना सकते हैं तो आपका परीक्षण टूटा हुआ है। इस रॉय ओशरोव ने ऐसी स्थितियों से बचने के लिए कहा: The Art Of Unit Testing (पूरी तरह से प्रकटीकरण के लिए लियो फ्राइडमैन (वह रॉय का मालिक था) मेरा मित्र है और मैंने 2 साल से अधिक समय तक उनके साथ मिलकर काम किया, इसलिए मैं थोड़ा सा हूँ पक्षपातपूर्ण ...)

मूल रूप से व्यवस्थित चरण (या उन चीजों के साथ जो अपवाद पैदा कर सकते हैं) के दौरान बाह्य संसाधनों के साथ बातचीत करने के कुछ कारण हैं, उनमें से अधिकतर (यदि उनमें से सभी नहीं) संबंधित हैं एकीकरण परीक्षण में।

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

निम्नलिखित पैटर्न, विफलता के लिए संभावना कम होती है जब से तुम बाहरी संसाधन को कम कॉल:

class TestClass(unittest.TestCase): 

    def setUpClass(self): 
     # since external resources such as other servers can provide a bad content 
     # you can verify that the content is valid 
     # then prevent from the tests to run 
     # however, in most cases you shouldn't. 
     self.externalResourceContent = loadContentFromExternalResource() 


    def setUp(self): 
     self.content = self.copyContentForTest() 

सकारात्मक: विफलता

  • विसंगति व्यवहार को रोकने के लिए

    1. कम संभावना है कि (1 कुछ/किसी ने बाहरी संसाधन को संपादित किया है। 2. आप अपने कुछ परीक्षणों में बाहरी संसाधन लोड करने में विफल रहे हैं)
    2. तेज निष्पादन

    विपक्ष:

    1. कोड और अधिक जटिल
  • 5

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

    +0

    तो आप एक स्वचालित निर्माण के माहौल में उस पर प्रकाश डाला जाना चाहिए? –

    +3

    @ जोनकेज आईएमएचओ यदि आपको वास्तव में पूर्व शर्त का परीक्षण करने की आवश्यकता है तो आपको उनके लिए एक परीक्षा लिखनी चाहिए और यह सुनिश्चित करने के लिए कि आपकी पूर्व शर्त वैध हैं, 'setUp()' का उपयोग न करें। तो 'test_load_fixture (self) जैसे एक टेस्ट जोड़ें: self.assertIsNotNone (self.content, "परीक्षण डेटा लोड करने में विफल")' और आपको इस परीक्षण के लिए एक त्रुटि होगी और प्रत्येक परीक्षण के लिए असफल होगा जो 'self.content' '। –

    2

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

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

    यह एक परीक्षण करने वाला थोड़ा क्लीनर है जो इन स्टार्टअप स्थितियों को व्यक्तिगत रूप से जांचता है और इसे पहले चलाता है, उन्हें प्रत्येक परीक्षण के बीच में आवश्यकता नहीं हो सकती है। यदि आप इसे test_01_check_preconditions के रूप में परिभाषित करते हैं तो यह किसी भी अन्य परीक्षण विधियों से पहले किया जाएगा, भले ही शेष यादृच्छिक हों। फिर भी आप कुछ शर्तों के लिए unittest2.skip सजावट का उपयोग कर सकते हैं।

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

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

    भी एक साधारण परीक्षण परिभाषा से परे unittest2 subclass करने के लिए लुभाने के लिए प्रलोभन नहीं है, मैंने देखा है कि लोग परीक्षण करने के लिए ऐसा करने की कोशिश करते हैं और वास्तव में पूरी तरह से अप्रत्याशित व्यवहार पेश करते हैं।

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

    3
    Python Standard Library Documentation से

    : विधि

    "जबकि परीक्षण चल रहा है, सेटअप() विधि एक अपवाद को जन्म देती है तो ढांचा परीक्षण पर विचार करेंगे एक त्रुटि का सामना करना पड़ा है, और runTest() होगा निष्पादित नहीं किया गया है। यदि setUp() सफल हुआ, tearDown() विधि चलाया जाएगा कि रनटेस्ट() सफल हुआ या नहीं। ऐसे परीक्षण कोड के लिए एक कार्य वातावरण को स्थिरता कहा जाता है।"

    विधि सेटअप() में एक अभिकथन अपवाद unittest ढांचे द्वारा एक त्रुटि के रूप में विचार किया जाएगा। परीक्षण निष्पादित नहीं किया जाएगा।

    2

    वहाँ एक कारण है कि आप एक setUp() में दावे से बचना चाहते हैं है। यदि सेटअप विफल हो जाता है, तो आपके आंसूडाउन निष्पादित नहीं होंगे।

    यदि आप उदाहरण के लिए डेटाबेस रिकॉर्ड का एक सेट सेट करते हैं और आपका टियरडाउन इन रिकॉर्ड्स को हटा देता है, तो इन रिकॉर्ड्स को हटाया नहीं जाएगा।

    इस स्निपेट के साथ

    :

    import unittest 
    
    class Test_test2(unittest.TestCase): 
    
        def setUp(self): 
         print 'setup' 
         assert False 
    
        def test_ProcessData(self): 
         print 'testing' 
    
        def tearDown(self): 
         print 'teardown' 
    
    if __name__ == '__main__': 
        unittest.main() 
    

    आप केवल setUp() चलाएँ:

    $ python t.py 
    setup 
    E 
    ====================================================================== 
    ERROR: test_ProcessData (__main__.Test_test2) 
    ---------------------------------------------------------------------- 
    Traceback (most recent call last): 
        File "t.py", line 7, in setUp 
        assert False 
    AssertionError 
    
    ---------------------------------------------------------------------- 
    Ran 1 test in 0.000s 
    
    FAILED (errors=1) 
    
    संबंधित मुद्दे