2009-06-28 6 views
5

मैं पाइथन सीख रहा हूं और पाइथन के unittest मॉड्यूल के विवरण के बारे में और अधिक समझने की कोशिश कर रहा हूं। प्रलेखन निम्नलिखित शामिल हैं:पायथन के साथ, मैं "कॉल करने योग्य ऑब्जेक्ट जो टेस्ट सूट देता है" कैसे बना और उपयोग कर सकता हूं?

चल परीक्षण की आसानी के लिए, जैसा कि हम बाद में देखेंगे, यह एक अच्छा विचार है एक प्रतिदेय उद्देश्य यह है कि पहले से बने परीक्षण, प्रत्येक परीक्षा मॉड्यूल में प्रदान करने के लिए सूट:

def suite(): 
    suite = unittest.TestSuite() 
    suite.addTest(WidgetTestCase('testDefaultSize')) 
    suite.addTest(WidgetTestCase('testResize')) 
    return suite 

जहां तक ​​मेरा बता सकते हैं, ऐसा करने का उद्देश्य नहीं समझाया गया है। इसके अलावा, मैं यह समझने में असमर्थ था कि कोई इस तरह की विधि का उपयोग कैसे करेगा। मैं सफलता के बिना कई बातें करने की कोशिश की (एक तरफ त्रुटि संदेश मुझे मिल गया के बारे में सीखने से):

import unittest 

def average(values): 
    return sum(values)/len(values) 

class MyTestCase(unittest.TestCase): 
    def testFoo(self): 
     self.assertEqual(average([10,100]),55) 

    def testBar(self): 
     self.assertEqual(average([11]),11) 

    def testBaz(self): 
     self.assertEqual(average([20,20]),20) 

    def suite(): 
     suite = unittest.TestSuite() 
     suite.addTest(MyTestCase('testFoo')) 
     suite.addTest(MyTestCase('testBar')) 
     suite.addTest(MyTestCase('testBaz')) 
     return suite 

if __name__ == '__main__': 
    # s = MyTestCase.suite() 
    # TypeError: unbound method suite() must be called 
    # with MyTestCase instance as first argument 

    # s = MyTestCase.suite(MyTestCase()) 
    # ValueError: no such test method in <class '__main__.MyTestCase'>: runTest 

    # s = MyTestCase.suite(MyTestCase('testFoo')) 
    # TypeError: suite() takes no arguments (1 given) 

"काम" निम्नलिखित लेकिन अजीब लगता है और यह आवश्यक है कि मैं 'def suite(self):' के लिए suite() की विधि हस्ताक्षर बदल जाते हैं।

s = MyTestCase('testFoo').suite() 
unittest.TextTestRunner().run(s) 

उत्तर

6

आपके द्वारा प्राप्त किया गया पहला त्रुटि संदेश सार्थक है, और बहुत कुछ बताता है।

print MyTestCase.suite # <unbound method MyTestCase.suite> 

अनबाउंड। इसका मतलब है कि आप इसे तब तक कॉल नहीं कर सकते जब तक कि आप इसे किसी उदाहरण में बाध्य न करें। यह वास्तव में MyTestCase.run के लिए एक ही है:

print MyTestCase.run # <unbound method MyTestCase.run> 

हो सकता है कि अब के लिए आप समझ में नहीं आता क्यों तुम suite कॉल नहीं कर सकते, लेकिन अब के लिए एक तरफ छोड़ दें। क्या आप ऊपर की तरह कक्षा पर run पर कॉल करने का प्रयास करेंगे? कुछ ऐसा:

MyTestCase.run() # ? 

शायद नहीं, है ना? इसे लिखने में कोई अर्थ नहीं है, और यह काम नहीं करेगा, क्योंकि run एक उदाहरण विधि है, और काम करने के लिए self उदाहरण की आवश्यकता है। वैसे ऐसा लगता है कि पायथन "" समझता है उसी तरह यह run को एक अनबाउंड विधि के रूप में समझता है।

चलो देखते हैं क्यों:

आप वर्ग क्षेत्र से बाहर suite विधि डाल दिया, और एक वैश्विक समारोह के रूप में यह परिभाषित करने की कोशिश करते हैं, तो यह सिर्फ काम करता है:

import unittest 

def average(values): 
    return sum(values)/len(values) 

class MyTestCase(unittest.TestCase): 
    def testFoo(self): 
     self.assertEqual(average([10,100]),55) 

    def testBar(self): 
     self.assertEqual(average([11]),11) 

    def testBaz(self): 
     self.assertEqual(average([20,20]),20) 

def suite(): 
    suite = unittest.TestSuite() 
    suite.addTest(MyTestCase('testFoo')) 
    suite.addTest(MyTestCase('testBar')) 
    suite.addTest(MyTestCase('testBaz')) 
    return suite 

print suite() # <unittest.TestSuite tests=[<__main__.MyTestCase testMethod=testFoo>, <__main__.MyTestCase testMethod=testBar>, <__main__.MyTestCase testMethod=testBaz>]> 

लेकिन तुम नहीं , वर्ग क्षेत्र से बाहर यह चाहते हैं, क्योंकि आप MyTestCase.suite()

तुम शायद सोचा था कि के बाद से suite था एक तरह से "स्थिर", या उदाहरण के स्वतंत्र है, यह मतलब नहीं था कि एक self argume डाल करने के लिए कॉल करना चाहते हैं एनटी, क्या तुमने? यह सही है।

लेकिन यदि आप पाइथन कक्षा के अंदर कोई विधि परिभाषित करते हैं, तो पाइथन उस विधि को self तर्क को पहली तर्क के रूप में उम्मीद करेगा। बस self तर्क को छोड़कर आपकी विधि static स्वचालित रूप से नहीं बनती है। यदि आप एक "स्थिर" विधि को परिभाषित करना चाहते हैं, तो आप staticmethod डेकोरेटर का उपयोग करना होगा:

@staticmethod 
def suite(): 
    suite = unittest.TestSuite() 
    suite.addTest(MyTestCase('testFoo')) 
    suite.addTest(MyTestCase('testBar')) 
    suite.addTest(MyTestCase('testBaz')) 
    return suite 

इस तरह अजगर एक उदाहरण विधि के रूप में MyTestCase पर विचार नहीं करता, लेकिन एक समारोह के रूप:

print MyTestCase.suite # <function suite at 0x...> 

और बेशक अब आप MyTestCase.suite() पर कॉल कर सकते हैं, और यह उम्मीद के अनुसार काम करेगा।

if __name__ == '__main__': 
    s = MyTestCase.suite() 
    unittest.TextTestRunner().run(s) # Ran 3 tests in 0.000s, OK 
1

documentation कह रहा है suite(), मॉड्यूल में एक समारोह होना चाहिए बल्कि अपनी कक्षा में एक विधि की तुलना में। यह केवल एक सुविधा समारोह प्रतीत होता है ताकि आप कई मॉड्यूल के लिए बाद में कुल परीक्षण स्वीट कर सकते हैं:

alltests = unittest.TestSuite([ 
    my_module_1.suite(), 
    my_module_2.suite(), 
]) 

आपका अपने कार्य बुला सब यह कक्षा में एक विधि से किया जा रहा से जुड़े हुए हैं के साथ समस्याओं, अभी नहीं एक विधि के रूप में लिखा । self पैरामीटर "वर्तमान ऑब्जेक्ट" है, और उदाहरण विधियों के लिए आवश्यक है। (उदा। a.b(1, 2) अवधारणात्मक रूप से b(a, 1, 2) जैसा ही है।) यदि विधि उदाहरणों के बजाय कक्षा पर चलती है, तो classmethod पढ़ें। यदि इसे सुविधा के लिए कक्षा के साथ समूहीकृत किया गया है लेकिन कक्षा और न ही उदाहरणों पर काम नहीं करता है, तो staticmethod पढ़ें। इनमें से कोई भी विशेष रूप से unittest का उपयोग करने में आपकी सहायता करेगा, लेकिन वे यह समझाने में सहायता कर सकते हैं कि आपने जो देखा वह आपने क्यों देखा।

1

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

1

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

0

मैं निम्नलिखित का उपयोग करने का सुझाव दूंगा। यह आपके द्वारा जोड़े जाने वाले सभी परीक्षणों को मैन्युअल रूप से दर्ज करने से बचाता है।

def suite(): 
    suite = unittest.TestLoader().loadTestsFromTestCase(Your_Test_Case_Class) 
    return suite 

यह आपको लचीलापन को परिभाषित करते हुए एक ही मॉड्यूल में परीक्षण निष्पादित करने के लिए देता है: तो,

if __name__ == "__main__": 
    suite() 

और अगर आप एक और मॉड्यूल यानी test_suite.py (उदाहरण के लिए) में अपने सूट बंडल करना चाहते हैं यह निम्नलिखित माध्यम से किया जा सकता है:

आयात test_module नाम आयात unittest

if __name__=="__main__": 
    suite1=test_module_name.suite() 
    ... 
    ... 
    alltests = unittest.TestSuite([suite1,suite2]) 

अब अपने परीक्षण कैसे चलाएं।मैं आम तौर पर पैकेज स्तर पर इस कमांड को क्रियान्वित चलाने के लिए सरल तरीके से उपयोग करें, और unittest स्वचालित रूप से परीक्षण को पता चलता है:

python -m unittest discover 

या

nosetests 

चेतावनी: X बार unittest है तेजी से तो nosetest , तो उसके बाद डेवलपर्स वरीयताओं तक विशेष रूप से यदि उन्होंने तीसरे पक्ष के सबसे बड़े प्लगइन का उपयोग किया है और इसका उपयोग करना जारी रखना चाहते हैं।

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

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