2010-06-24 7 views
5

मेरा परीक्षण ढांचा वर्तमान में एक परीक्षण-धावक उपयोगिता पर आधारित है जो स्वयं ग्रहण पाइडव पायथन से लिया गया है परीक्षण धावक। मैं नाक का उपयोग करने के लिए स्विच कर रहा हूं, जिसमें मेरे कस्टम टेस्ट-रनर की कई विशेषताएं हैं लेकिन बेहतर गुणवत्ता कोड प्रतीत होता है।क्या नाक केवल टेस्टकेस या टेस्टसाइट (जैसे unittest.main()) के उप-वर्ग हैं, जैसे

मेरा परीक्षण सूट में कई अमूर्त परीक्षण-वर्ग शामिल हैं जो पहले कभी नहीं दौड़ते थे। मानक पायथन testrunner (और मेरा कस्टम एक) केवल unittest के उदाहरण भाग गया। टेस्टकेस और unittest.TestSuite।

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

स्पष्ट रूप से मैं उनके नाम से "परीक्षण" शब्द को बाहर करने के तरीकों का पुनः नाम दे सकता हूं ... इसमें कुछ समय लगेगा क्योंकि परीक्षण ढांचा बहुत बड़ा है और इसमें बहुत अधिक विरासत है। दूसरी ओर यह नाट बनाने का कोई तरीका था जब नाक को केवल टेस्टकेसेस और टेस्टसाइट्स को चलाने योग्य होने के रूप में देखा गया था ... और कुछ भी नहीं।

क्या यह किया जा सकता है?

उत्तर

5

आप nosetests के लिए -m विकल्प के साथ खेलने का प्रयास कर सकते हैं। प्रलेखन से:

एक परीक्षण वर्ग एक वर्ग एक परीक्षण मॉड्यूल testMatch या मैचों में परिभाषित unittest.TestCase

-m सेट कि testMatch का एक उपवर्ग, इस तरह से आप परीक्षण निष्क्रिय कर सकते हैं कर रहा है परीक्षण से शुरू कुछ भी।

एक और बात यह है कि आप अपने टेस्ट केस क्लास घोषणा में __test__ = False जोड़ सकते हैं, इसे "परीक्षण नहीं" चिह्नित करने के लिए।

+0

'__test__ = FALSE' चाल बहुत उपयोगी नहीं है एक माता पिता के वर्ग के मामले में, यह बच्चों को स्पष्ट रूप से निर्दिष्ट करने के लिए मजबूर होना पड़ा कक्षाएं' __test__ = TRUE' या यह नजरअंदाज कर दिया जाएगा, जो एक खतरनाक है उपयोग करने के लिए चाल। – Guibod

0

आप नाक के --attr तर्क का उपयोग unittest.TestCase द्वारा निर्धारित विशेषता निर्दिष्ट करने के लिए कर सकते हैं। उदाहरण के लिए, मैं का उपयोग करें:

nosetests --attr="assertAlmostEqual" 

आप और और या मिलान का उपयोग करके और भी अधिक सावधान हो सकता है:

nosetests -A "assertAlmostEqual or addTest" 

तरीकों की एक पूरी सूची के लिए unittest's documentation देखें/गुण, और नाक के description of the capabilities of the --attr plugin

2

यदि आप वास्तव में अमूर्त परीक्षा वर्ग चाहते हैं, तो आप ऑब्जेक्ट से सार तत्व को प्राप्त कर सकते हैं, फिर बाद में टेस्टकेस में उत्तराधिकारी हो सकते हैं।

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

class AbstractTestcases(object): 
    def test_my_function_does_something(self): 
     self.assertEquals("bar", self.func()) 

और फिर साथ उपयोग:

class TestMyFooFunc(AbstractTestcases, unittest.TestCase): 
    def setUp(self): 
     self.func = lambda: "foo" 

फिर nosetestsTestMyFooFunc में केवल testcases लेने और नहीं होगा AbstractTestCases में उन।@nailxx के जवाब देने के लिए

+0

समस्या से बचने का यह एक अच्छा तरीका है, लेकिन अमूर्त परीक्षण तब मेरे आईडीई में काफी पढ़ा जा सकता है। – Guibod

0

एक परिशिष्ट:

आप माता-पिता कक्षा में __test__ = False सेट कर सकते हैं और फिर जब उपवर्गीकरण सच में पुन: स्थापित करने के लिए एक metaclass (कुछ प्रतिभाशाली स्पष्टीकरण के साथ This question देखें) का उपयोग करें।

(अंत में, मैं एक बहाना एक metaclass उपयोग करने के लिए मिल गया!)

हालांकि __test__ एक डबल अंडरस्कोर विशेषता है, हम स्पष्ट रूप से, True के लिए सेट की स्थापना नहीं के बाद से यह सिर्फ देखने के लिए अजगर का कारण होगा करने के लिए है विशेषता MRO को आगे बढ़ाएं और इसे False पर मूल्यांकन करें।

इस प्रकार, हमें क्लास इंस्टेंटेशन पर जांच करने की आवश्यकता है कि क्या माता-पिता वर्गों में से एक __test__ = False है। यदि यह मामला है और वर्तमान श्रेणी परिभाषा ने __test__ स्वयं सेट नहीं किया है, तो हम गुणों के लिए '__test__': True जोड़ देंगे।

class TestWhenSubclassedMeta(type): 
    """Metaclass that sets `__test__` back to `True` when subclassed. 

    Usage: 

     >>> class GenericTestCase(TestCase, metaclass=TestWhenSubclassed): 
     ...  __test__ = False 
     ... 
     ...  def test_something(self): 
     ...   self.fail("This test is executed in a subclass, only.") 
     ... 
     ... 
     >>> class SpecificTestCase(GenericTestCase): 
     ...  pass 

    """ 

    def __new__(mcs, name, bases, attrs): 
     ATTR_NAME = '__test__' 
     VALUE_TO_RESET = False 
     RESET_VALUE = True 

     values = [getattr(base, ATTR_NAME) for base in bases 
        if hasattr(base, ATTR_NAME)] 

     # only reset if the first attribute is `VALUE_TO_RESET` 
     try: 
      first_value = values[0] 
     except IndexError: 
      pass 
     else: 
      if first_value == VALUE_TO_RESET and ATTR_NAME not in attrs: 
       attrs[ATTR_NAME] = RESET_VALUE 

     return super().__new__(mcs, name, bases, attrs) 

एक तरह "अगर नाम Abstract साथ शुरू होता है, __test__ = False स्वचालित रूप से सेट" कुछ और अंतर्निहित व्यवहार को यह विस्तार सकता है, लेकिन मैं अपने आप को स्पष्ट काम रखना होगा:

जिसके परिणामस्वरूप कोड इस तरह दिखता है विस्तृत जानकारी के लिए।


मुझे व्यवहार प्रदर्शित करने के लिए सरल unittests पेस्ट करते हैं - और एक चेतावनी के रूप में सभी एक सुविधा शुरू करने के बाद अपने कोड का परीक्षण करने के लिए दो मिनट का समय चाहिए।

from unittest import TestCase 

from .base import TestWhenSubclassedMeta 


class SubclassesTestCase(TestCase): 
    def test_subclass_resetted(self): 
     class Base(metaclass=TestWhenSubclassedMeta): 
      __test__ = False 

     class C(Base): 
      pass 

     self.assertTrue(C.__test__) 
     self.assertIn('__test__', C.__dict__) 

    def test_subclass_not_resetted(self): 
     class Base(metaclass=TestWhenSubclassedMeta): 
      __test__ = True 

     class C(Base): 
      pass 

     self.assertTrue(C.__test__) 
     self.assertNotIn('__test__', C.__dict__) 

    def test_subclass_attr_not_set(self): 
     class Base(metaclass=TestWhenSubclassedMeta): 
      pass 

     class C(Base): 
      pass 

     with self.assertRaises(AttributeError): 
      getattr(C, '__test__') 
0

तुम भी परीक्षण का मामला स्तर पर एकाधिक वंशानुक्रम का उपयोग करें और केवल object से आधार वर्ग इनहेरिट दे सकते हैं। this thread देखें:

class MyBase(object): 
    def finishsetup(self): 
     self.z=self.x+self.y 

    def test1(self): 
     self.assertEqual(self.z, self.x+self.y) 

    def test2(self): 
     self.assert_(self.x > self.y) 

class RealCase1(MyBase, unittest.TestCase): 
    def setUp(self): 
     self.x=10 
     self.y=5 
     MyBase.finishsetup(self) 

class RealCase2(MyBase, unittest.TestCase): 
    def setUp(self): 
     self.x=42 
     self.y=13 
     MyBase.finishsetup(self)