2010-05-11 20 views
11

मेरे पास एक ऐसी स्क्रिप्ट है जो sys.argv का उपयोग करके विभिन्न चीजें और एक्सेस पैरामेंटर्स करती है लेकिन जब स्क्रिप्ट कोड के सबसे अजीब हिस्से में जाती है तो यह कहती है कि वहां कोई नहीं है इसके लिए मॉड्यूल। स्क्रिप्ट मेरे पास है वह यह है कि:sys.argv [1] के साथ समस्या जब unittest मॉड्यूल एक स्क्रिप्ट में है

class MyScript(): 

    def __init__(self): 
     self.value = sys.argv[1] 

    def hello(self): 
     print self.value 

    def suite(self): 
     modules_to_test = ('external_sanity_onvif', 'starttest') 
     alltests = unittest.TestSuite() 
     for module in map(__import__, modules_to_test): 
      alltests.addTest(unittest.findTestCases(module)) 
     return alltests 


if __name__ == '__main__': 
    Run = MyScript() 
    Run.hello() 
    log_file = 'log_file.txt' 
    test_file = open(log_file, "w") 
    runner = unittest.TextTestRunner(test_file) 
    unittest.main(defaultTest='Run.suite', testRunner=runner) 

मैं कमांड लाइन में ./script.py Hello दर्ज कहो। मुझे जो त्रुटि मिलती है वह है:

AttributeError: 'module' object has no attribute 'Hello' 

यदि मैं अनजान मॉड्यूल को हटा देता हूं तो यह काम करता है। इसके अलावा यदि मैं testrunner लॉग को हटा देता हूं और इसे छोड़ देता हूं:

unittest.main(defaultTest='Run.suite') 

यह अभी भी काम नहीं करता है।

कोई भी मदद कर सकता है।

धन्यवाद

मैं इस हैक करने की कोशिश की लेकिन यह अभी भी sys.argv को पढ़ने के लिए कोशिश करता है।

project = sys.argv[4:] 
sys.argv = sys.argv[0:4] 

मैं सिर्फ argv के साथ इस की कोशिश की है लेकिन यह अभी भी टायर अतिरिक्त पैरामीटर को पढ़ने के लिए।

+1

आप (स्टैक ट्रेस के साथ) पूर्ण त्रुटि संदेश पोस्ट कर सकता है? यह हमें बताएगा कि 'AttributeError' किस पंक्ति में हुआ था। – unutbu

उत्तर

16

समस्या यह है कि unittest.main() अपने बहुमूल्य argv अपने स्वयं के उपयोग के लिए चाहता है! यह या तो argv का उपयोग करता है जिसे आप इसे फ़ंक्शन पैरामीटर के रूप में देते हैं, या sys.argv यदि आप इसे स्पष्ट रूप से argv नहीं देते हैं, और आपके द्वारा दिए गए तर्कों के नामों को लोड करने का प्रयास करते हैं। इस मामले में, इसका मतलब यह है कि यह सब के भीतर या तो एक submodule Hello कहा जाता है, एक TestCase वर्ग Hello, एक परीक्षण मामला वर्ग Hello नाम है, या एक प्रतिदेय उद्देश्य यह है कि एक TestCase या TestSuite उदाहरण देता Hello कहा जाता है के भीतर एक परीक्षण का मामला विधि नामित की तलाश में, अपने मॉड्यूल 'स्क्रिप्ट'।

  • बाईपास unittest.main() और निचले स्तर unittest खुद के काम करता है परीक्षण मामलों आपके मन में है की स्थापना की और चलाने के लिए कॉल करें:

    इसे ठीक करने के कई तरीके हैं।

  • sys.argv पर अपने कोड की निर्भरता को हटाएं, और अपने लाभ के लिए unittest.main() व्यवहार का उपयोग करें। यदि आपका मॉड्यूल स्वतंत्र रूप से को यूनिट परीक्षण के रूप में को छोड़कर चलाने के लिए नहीं है, तो शायद यह समझ में आता है, क्योंकि आपके मॉड्यूल के कॉलर्स आपको उनके तर्क से पढ़ने की उम्मीद नहीं कर रहे हैं!
  • परीक्षण कोड और मुख्य दिनचर्या को एक अलग परीक्षण मॉड्यूल में अलग करें।परीक्षण मॉड्यूल से आपको अभी भी अपने कोड में सही argv कैसे प्राप्त करना है, यह पता लगाना होगा।
  • पर तर्क के रूप में argv=[sys.argv[0]] निर्दिष्ट करें; इसे इसे पढ़ने की कोशिश करने से रोकना चाहिए।
-1

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

क्या कोई कारण है कि आप केवल unittest.main() का उपयोग नहीं कर रहे हैं?

+2

कोड के इस विशेष पाइस में मैं हैलो को पैरामीटर के रूप में पास करने की कोशिश कर रहा हूं जो काम करेगा। तब मेरे पास एक ऐसा फ़ंक्शन है जो परीक्षण की एक श्रृंखला को कॉल करता है जो अन्य कार्यों से अलग है। लेकिन जब एकजुट और sys.argv एक ही लिपि में हैं तो एक समस्या है। जिन परीक्षणों से मैं काम कर रहा हूं, वे कोई फर्क नहीं पड़ता कि वे काम करते हैं, समस्या यह है कि जब मैं किसी फंक्शन में पैरामीटर दर्ज करता हूं और बिना किसी लिंक के एक पैरामीटर दर्ज करता हूं और फिर फ़ाइल के नीचे अनजान फ़ंक्शन चलाता है तो मुझे त्रुटि मिलती है। उस प्रकार का यूनिटस्ट कमांड का उपयोग करने का कारण यह है कि मैं एक विशिष्ट परीक्षण सूट बुला रहा हूं। – chrissygormley

+0

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

1

आम तौर पर, यूनिट परीक्षण के पीछे विचार यह है कि बाहरी ड्राइवर के बिना परीक्षण चलते हैं। जैसे आप कमांड लाइन से कुछ इनपुट पर निर्भर नहीं होना चाहते हैं। जो समाधान आप खोज रहे हैं वह फिक्स्चर के उपयोग के माध्यम से हो सकता है?

import sys 
import unittest 

class MyScript(unittest.TestCase): 
    def setUp(self): 
     self.value = "Default Value" 

    def setHello(self, value): 
     self.value = value 

    def hello(self): 
     return self.value 

class UserA(MyScript): 
    def setUp(self): 
     self.setHello("UserA") 

    def testMyName(self): 
     self.failUnlessEqual(self.hello(), "UserA") 

class UserB(MyScript): 
    def setUp(self): 
     self.setHello("UserB") 

    def testMyName(self): 
     self.failUnlessEqual(self.hello(), "UserB") 

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

आप unittest मॉड्यूल के कमांड लाइन सुविधाओं की जरूरत नहीं है, तो आप बस बुला unittest.main()

बस से पहले यह कोशिश करो इससे पहले कि optparse और unittest मॉड्यूल sys.argv संशोधित करके एक साथ अच्छी तरह से खेलते बना सकते हैं अपने unittest.main() कॉल:

del sys.argv[1:] 

यह आपके आदेश पंक्ति तर्क से पहले unittest उन्हें देखता निकाल देता है।

आप optparse मॉड्यूल का उपयोग नहीं कर रहे हैं, तो आप के बजाय यह कर सकते हैं:

my_args = sys.argv[1:] 
del sys.argv[1:] 
# do_stuff(my_args) 
unittest.main()