2010-12-30 9 views
33

का उपयोग कर सार परीक्षण केस क्या एक सार TestCase बनाना संभव है, जिसमें कुछ test_ * विधियां होंगी, लेकिन यह TestCase नहीं कहा जाएगा और उन विधियों का उपयोग उप-वर्गों में ही किया जाएगा? मुझे लगता है कि मेरे टेस्ट सूट में एक सार TestCase होगा और इसे एक इंटरफ़ेस के कुछ अलग कार्यान्वयन के लिए उप-वर्गीकृत किया जाएगा। यही कारण है कि सभी परीक्षण विधियां कुछ हैं, केवल एक, आंतरिक विधि में परिवर्तन। मैं इसे सुरुचिपूर्ण तरीके से कैसे कर सकता हूं?पाइथन unittest

+2

यदि आप अपने परीक्षण चलाने के लिए नाक का उपयोग करते हैं तो यह कुछ आसान हो सकता है। [ढूँढना और परीक्षण चलाना] देखें (http://somethingaboutorange.com/mrl/projects/nose/1.0.0/finding_tests.html)। नाक के साथ आप उदाहरण के लिए, अपनी बेस क्लास में '__test __ = गलत' डाल सकते हैं। – bstpierre

+0

मेरे सार परीक्षण मामले पर छोड़ने के बारे में कैसे? – gruszczy

+0

@bstpierre महान सुझाव। जो मेरे लिए पूरी तरह से काम करता है –

उत्तर

52

मैं काफी है कि आप क्या करने की योजना है समझ में नहीं आया - अंगूठे का नियम "परीक्षण के साथ स्मार्ट नहीं होने के लिए" है - सिर्फ उन्हें वहाँ है, सादा लिखा।

लेकिन जो भी आप चाहते हैं उसे प्राप्त करने के लिए, यदि आप unittest से प्राप्त करते हैं। टेस्टकेस, जब भी आप unittest.main() को कॉल करते हैं तो आपकी "अमूर्त" कक्षा निष्पादित की जाएगी - मुझे लगता है कि यह वह स्थिति है जिसे आप टालना चाहते हैं।

बस यह करें: टेस्टकेस से नहीं, "ऑब्जेक्ट" से विरासत में अपना "अमूर्त" वर्ग बनाएं। और वास्तविक "कंक्रीट" कार्यान्वयन के लिए, केवल एकाधिक विरासत का उपयोग करें: दोनों unittest.TestCase और आपके सार वर्ग से प्राप्त होता है।

import unittest 

class Abstract(object): 
    def test_a(self): 
     print "Running for class", self.__class__ 

class Test(Abstract, unittest.TestCase): 
    pass 

unittest.main() 

अद्यतन: विरासत आदेश वापस ले लिया - Abstract पहले तो यह है कि अपनी defintions, TestCase चूक द्वारा ओवरराइड नहीं कर रहे हैं और साथ ही टिप्पणी bellow में इशारा किया।

+2

इस तरह मैं इसे पहले स्थान पर करना चाहता था। मैं स्मार्ट बनना चाहता हूं, क्योंकि मैं अलग-अलग डेटाबेस के खिलाफ अपना परीक्षण चला रहा हूं। डेटाबेस तक पहुंचने के लिए इंटरफ़ेस हमेशा समान होता है, इसलिए मुझे डेटाबेस से अपने कनेक्शन को तुरंत चालू करने की आवश्यकता होती है और हमेशा एक ही परीक्षण चलाया जाता है। मुझे नहीं पता, अगर यह परीक्षण के लिए बहुत चालाक है, लेकिन मुझे बस इतना टाइप करना पसंद नहीं है ;-) – gruszczy

+0

हां, मैं दस डी को "चीजों को स्मार्ट बनाने" पसंद करता हूं। तो ... क्या आप स्पष्ट कर सकते हैं कि मेरे उत्तर में क्या गुम है? कमांड लाइन पैरामीटर के आधार पर testCase कक्षाओं में परीक्षण विधियों को "प्लग" करने के तरीके हैं, आपको पता है ... – jsbueno

+0

जब मैं काम पर नहीं हूं, तो मुझे चीजें बहुत स्मार्ट करना पसंद है। इस तरह से मैं और जान सकता हूं, भले ही मैंने रास्ते पर कुछ खींचा :-) यहां कोई जोखिम नहीं है। – gruszczy

3

आप स्पष्ट रूप से run_unittest में सभी परीक्षण कक्षाओं लिस्टिंग के सम्मेलन (देखें उदाहरण के लिए कि सम्मेलन के कई उपयोगों के लिए अजगर टेस्ट स्वीट) का पालन करें, तो यह नहीं सूची किसी विशेष वर्ग के लिए सीधी-सपाट हो जाएगा।

यदि आप unittest.main का उपयोग करना जारी रखना चाहते हैं, और यदि आप unittest2 (उदा। पायथन 2.7 से) का उपयोग करने की अनुमति दे सकते हैं, तो आप यह निर्धारित करने के लिए अपने load_tests प्रोटोकॉल का उपयोग कर सकते हैं कि कौन से वर्ग परीक्षण मामलों में हैं)। पिछले संस्करणों में, आपको TestLoader को उपclass करना होगा, और loadTestsFromModule ओवरराइड करना होगा।

+0

जीत मैं कमांड लाइन से उन परीक्षणों को आह्वान करने की क्षमता खो देता हूं? मैं डिफ़ॉल्ट रूप से सभी परीक्षणों को चलाता हूं (सार परीक्षण मामले से बाहर को छोड़कर), लेकिन कुछ मामलों में केवल उनमें से कुछ। – gruszczy

+0

@gruszczy: मेरा संपादन देखें। –

9

एकाधिक वंशानुक्रम नहीं एक बढ़िया विकल्प यहाँ, मुख्यतः दो निम्नलिखित कारणों के लिए है:

  1. TestCase उपयोग super() में तरीकों में से कोई भी, ताकि आप setUp() और तरह के तरीकों के लिए पहली बार अपने वर्ग की सूची करना होगा काम करने के लिए tearDown()
  2. पिलिंट चेतावनी देगा कि बेस क्लास self.assertEquals() आदि का उपयोग करता है जो उस बिंदु पर self पर परिभाषित नहीं हैं।

यहां मैं जिस क्लाउड के साथ आया था: केवल run() को बेस क्लास के लिए नो-ऑप में बदलें।

class TestBase(unittest.TestCase): 

    def __init__(self, *args, **kwargs): 
    super(TestBase, self).__init__(*args, **kwargs) 
    self.helper = None 
    # Kludge alert: We want this class to carry test cases without being run 
    # by the unit test framework, so the `run' method is overridden to do 
    # nothing. But in order for sub-classes to be able to do something when 
    # run is invoked, the constructor will rebind `run' from TestCase. 
    if self.__class__ != TestBase: 
     # Rebind `run' from the parent class. 
     self.run = unittest.TestCase.run.__get__(self, self.__class__)       
    else: 
     self.run = lambda self, *args, **kwargs: None 

    def newHelper(self): 
    raise NotImplementedError() 

    def setUp(self): 
    print "shared for all subclasses" 
    self.helper = self.newHelper() 

    def testFoo(self): 
    print "shared for all subclasses" 
    # test something with self.helper 

class Test1(TestBase): 
    def newHelper(self): 
    return HelperObject1() 

class Test2(TestBase): 
    def newHelper(self): 
    return HelperObject2() 
+3

(1) वास्तव में कोई समस्या नहीं है - ऐसा करने की स्पष्ट बात यह है कि आपकी कक्षा पहले आती है और सुपर का उपयोग करती है (मेरा जवाब यह उलटा हुआ था - मैंने इसे ठीक किया) । (2) आपके द्वारा उपयोग किए जाने वाले शब्द में यह कहा गया है - आपको "क्लेज" का उपयोग करना है, जो कि बहुत ही भिखारी से काम कर रहे पायथन के ओओपी में निर्मित एक स्वच्छ तंत्र का उपयोग न करें, क्योंकि एक तृतीय पक्ष लिनिंग उपकरण सही ढंग से आत्मनिरीक्षण नहीं कर सकता है। यह आपकी पसंद का औजार है। – jsbueno

7

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

from django.test import TestCase 


class _AbstractTestCase(TestCase): 

    """ 
    Abstract test case - should not be instantiated by the test runner. 
    """ 

    def test_1(self): 
     raise NotImplementedError() 

    def test_2(self): 
     raise NotImplementedError() 


class TestCase1(_AbstractTestCase): 

    """ 
    This test case will pass and fail. 
    """ 

    def test_1(self): 
     self.assertEqual(1 + 1, 2) 


class TestCase2(_AbstractTestCase): 

    """ 
    This test case will pass successfully. 
    """ 

    def test_1(self): 
     self.assertEqual(2 + 2, 4) 

    def test_2(self): 
     self.assertEqual(12 * 12, 144) 
+2

यह बहुत अच्छा काम करता प्रतीत होता है और यह ऊपर बंदर-पैच दृष्टिकोण से कहीं अधिक सरल है। – Fasaxc

+1

यह django (और मेरे मामले में, नाक के साथ) के साथ काम कर सकता है, लेकिन सबसे अजीब खोज तंत्र अभी भी इन अमूर्त परीक्षण मामलों को ढूंढता है ... –

+1

या तो django के साथ काम नहीं करता है। बस परीक्षण किया गया –

2

अजगर पुस्तकालय unittest load_tests protocol, जो प्राप्त करने के लिए आप वास्तव में क्या चाहते हैं इस्तेमाल किया जा सकता है:

# Add this function to module with AbstractTestCase class 
def load_tests(loader, tests, _): 
    result = [] 
    for test_case in tests: 
     if type(test_case._tests[0]) is AbstractTestCase: 
      continue 
     result.append(test_case) 
    return loader.suiteClass(result) 
2

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

आप हमेशा की तरह inheritence उपयोग करते हैं, तो जोड़ें:

del AbstractTestCase 

मॉड्यूल के अंत में।

+0

क्या कोई कमी है? –

+0

@MaxMalysh आप सुपरक्लास में पुरानी शैली की कॉल का उपयोग नहीं कर सकते हैं। लेकिन 'सुपर' अभी भी काम करता है, और हर किसी को वास्तव में * इसका उपयोग करना चाहिए। – o11c

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