2015-04-18 10 views
11

मेरे पास एक निर्देशिका "परीक्षण" वाला पैकेज है जिसमें मैं अपने यूनिट परीक्षणों को संग्रहीत कर रहा हूं। मेरे पैकेज लगता है:रिकर्सिव unittest खोज

. 
├── LICENSE 
├── models 
│   └── __init__.py 
├── README.md 
├── requirements.txt 
├── tc.py 
├── tests 
│   ├── db 
│   │   └── test_employee.py 
│   └── test_tc.py 
└── todo.txt 

अपने पैकेज निर्देशिका से, मैं tests/test_tc.py और tests/db/test_employee.py दोनों ढूँढने में सक्षम होना चाहता हूँ। मैं एक तीसरी पार्टी पुस्तकालय (nose या आदि) स्थापित करने या मैन्युअल रूप में इस चलाने के लिए एक TestSuite निर्माण करने के लिए नहीं करना चाहते।

निश्चित रूप से वहाँ एक रास्ता unittest discover बता देख रोकने के लिए नहीं करने के लिए एक बार यह एक पाया परीक्षा? python -m unittest discover -s teststests/test_tc.py और python -m unittest discover -s tests/db मिलेगा tests/db/test_employee.py मिलेगा। क्या दोनों को खोजने का कोई तरीका नहीं है?

+0

क्या आपने उदा। http://stackoverflow.com/q/644821/3001761? मुझे लगता है कि उनमें से कुछ उत्तरों को आपके उद्देश्यों के लिए अनुकूलित किया जा सकता है। – jonrsharpe

उत्तर

28

खुदाई करने में थोड़ा सा ऐसा लगता है कि जब तक गहरे मॉड्यूल आयात योग्य रहते हैं, तो उन्हें python -m unittest discover के माध्यम से खोजा जाएगा। समाधान, तो, उन्हें संकुल बनाने के लिए प्रत्येक निर्देशिका में __init__.py फ़ाइल जोड़ने के लिए बस था।

. 
├── LICENSE 
├── models 
│   └── __init__.py 
├── README.md 
├── requirements.txt 
├── tc.py 
├── tests 
│   ├── db 
│   │   ├── __init__.py  # NEW 
│   │   └── test_employee.py 
│   ├── __init__.py   # NEW 
│   └── test_tc.py 
└── todo.txt 

इतने लंबे समय के प्रत्येक निर्देशिका एक __init__.py है के रूप में, python -m unittest discover प्रासंगिक test_* मॉड्यूल आयात कर सकते हैं।

+3

मैं इसे सही उत्तर मानता हूं। –

4

यदि आप परीक्षण के अंदर __init__.py फ़ाइल जोड़ने के ठीक हैं, तो आप load_tests फ़ंक्शन डाल सकते हैं जो आपके लिए खोज को संभालेगा।

परीक्षण पैकेज का नाम (__init__.py साथ निर्देशिका) पैटर्न तो पैकेज एक 'load_tests' समारोह के लिए जाँच की जाएगी से मेल खाता है। यदि यह मौजूद है तो इसे लोडर, परीक्षण, पैटर्न के साथ बुलाया जाएगा।

load_tests तो मौजूद खोज पैकेज में नहीं recurse करता है, load_tests पैकेज में सभी परीक्षण लोड करने के लिए जिम्मेदार है।

मुझे विश्वास से दूर कर रहा हूँ कि यह सबसे अच्छा तरीका है, लेकिन एक ही रास्ता है कि समारोह में लिखने के लिए होगा:

import os 
import pkgutil 
import inspect 
import unittest 

# Add *all* subdirectories to this module's path 
__path__ = [x[0] for x in os.walk(os.path.dirname(__file__))] 

def load_tests(loader, suite, pattern): 
    for imp, modname, _ in pkgutil.walk_packages(__path__): 
     mod = imp.find_module(modname).load_module(modname) 
     for memname, memobj in inspect.getmembers(mod): 
      if inspect.isclass(memobj): 
       if issubclass(memobj, unittest.TestCase): 
        print("Found TestCase: {}".format(memobj)) 
        for test in loader.loadTestsFromTestCase(memobj): 
         print(" Found Test: {}".format(test)) 
         suite.addTest(test) 

    print("=" * 70) 
    return suite 

सुंदर बदसूरत, मैं सहमत हूँ।

सबसे पहले आप सभी उपनिर्देशिका परीक्षण पैकेज के पथ (Docs) में जोड़ते हैं।

फिर, आप पथ पर चलने के लिए pkgutil का उपयोग करते हैं, पैकेज या मॉड्यूल की तलाश करते हैं।

जब यह एक पाता है, तो यह मॉड्यूल सदस्यों को यह देखने के लिए जांचता है कि वे कक्षाएं हैं, और यदि वे कक्षाएं हैं, चाहे वे unittest.TestCase के उप-वर्ग हैं। यदि वे हैं, कक्षाओं के अंदर परीक्षण परीक्षण सूट में लोड कर रहे हैं।

तो अब, अपनी परियोजना के रूट के अंदर से, आप

python -m unittest discover -p tests 

टाइप -p पैटर्न स्विच का उपयोग कर सकते हैं। सब कुछ ठीक है, तुम मैं क्या देखा देखेंगे, जो की तरह कुछ है:

Found TestCase: <class 'test_tc.TestCase'> 
    Found Test: testBar (test_tc.TestCase) 
    Found Test: testFoo (test_tc.TestCase) 
Found TestCase: <class 'test_employee.TestCase'> 
    Found Test: testBar (test_employee.TestCase) 
    Found Test: testFoo (test_employee.TestCase) 
====================================================================== 
.... 
---------------------------------------------------------------------- 
Ran 4 tests in 0.001s 

OK 

है कौन क्या उम्मीद थी, मेरे दो उदाहरण फ़ाइलों में से प्रत्येक के दो टेस्ट, testFoo और testBar प्रत्येक निहित।

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

def load_tests(loader, suite, pattern): 
    for imp, modname, _ in pkgutil.walk_packages(__path__): 
     mod = imp.find_module(modname).load_module(modname) 
     for test in loader.loadTestsFromModule(mod): 
      print("Found Tests: {}".format(test._tests)) 
      suite.addTests(test) 

यह loader.loadTestsFromModule() विधि के बजाय का उपयोग करता है loader.loadTestsFromTestCase() विधि मैं ऊपर प्रयोग किया जाता है: कुछ और खुदाई के बाद, यह के रूप में की तरह आप इस समारोह निर्दिष्ट कर सकते हैं लग रहा है।यह अभी भी tests पैकेज पथ को संशोधित करता है और इसे मॉड्यूल की तलाश में चलता है, जो मुझे लगता है कि यहां कुंजी है।

उत्पादन अब कुछ अलग दिखाई देता है, हम हमारे मुख्य testsuite suite करने के लिए एक समय में एक पाया testsuite जोड़ रहे हैं के बाद से:

python -m unittest discover -p tests 
Found Tests: [<test_tc.TestCase testMethod=testBar>, <test_tc.TestCase testMethod=testFoo>] 
Found Tests: [<test_employee.TestCase testMethod=testBar>, <test_employee.TestCase testMethod=testFoo>] 
====================================================================== 
.... 
---------------------------------------------------------------------- 
Ran 4 tests in 0.000s 

OK 

लेकिन हम अभी भी 4 परीक्षण हम उम्मीद मिलता है, दोनों वर्गों में, दोनों उपनिर्देशिकाओं में।

+1

यह 'पायथन-एम अनइटेस्ट सर्च-टेस्ट - रिकर्सिव' की तुलना में काफी कठिन है, जो कि मैं वास्तव में उम्मीद कर रहा था कि किसी को मतदान करने से पहले टिप्पणी करने से पहले कोई टिप्पणी नहीं होगी। (यह कहना है, * धन्यवाद! *) –

+1

@ एडमस्मिथ कोई समस्या नहीं, मुझे उम्मीद है कि यह मदद करता है - खुदाई के बाद, एक ऐसी विधि बनती है जो थोड़ा सा सरल है, जो कि सबसे अजीब खोज पर अधिक निर्भर है मेरे पास स्पष्ट जांच थी - मैं इस विकल्प को शामिल करने के लिए अपना उत्तर संपादित करूंगा। – jedwards

+0

हम्म अभी तक एक आसान तरीका है जिसे मैंने गलती से खोजा है। मैं आत्म-जवाब दूंगा, हालांकि आपका अभी भी अधिक मूर्खतापूर्ण है। –

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