2008-11-28 4 views
8

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

def outer(): 
    def inner(): 
     pass 

outer.inner() 

जो त्रुटि संदेश में परिणाम:

AttributeError: 'function' object has no attribute 'inner'

वहाँ मेरे लिए एक तरह से इन नेस्ट कार्यों के खिलाफ इकाई परीक्षण लिखने के लिए है? यदि नहीं, तो फ़ंक्शन नामों के लिए नाम मंगिंग को ट्रिगर करने का कोई तरीका है जैसे आप वर्ग चर के लिए __ के साथ उपसर्ग करके कर सकते हैं?

उत्तर

5

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

याद रखें, Python is not Java

+11

कैसे इस सवाल का जवाब है? यूनिट परीक्षण के लिए ऐसे आंतरिक कार्यों को अलग करने के लिए अच्छे समाधान हैं या नहीं? यहां तक ​​कि बाहरी फ़ंक्शन ऑब्जेक्ट से भीतरी तक पहुंच के बिना, ऐसा लगता है कि कोड को पासा करने के लिए पाइथन मॉड्यूल पार्सर, अस्थ, या टोकनेज़र के उपयोग के साथ ऐसा प्रतीत होता है। स्पष्ट रूप से कोड अप करने की तुलना में राज्य करना आसान है। :-) –

+1

यह सवाल का जवाब देता है क्योंकि कोई * निजी * कार्यान्वयन विवरण * परीक्षण नहीं करता है। आप परीक्षण कवरेज टूल पर भरोसा कर सकते हैं ताकि आप यह बताने के लिए कि क्या आप सार्वजनिक इंटरफेस का परीक्षण निजी कार्यान्वयन का पर्याप्त अभ्यास करते हैं। – SingleNegationElimination

+0

@ टिम: प्रश्न में अंतिम वाक्य के आधार पर, लेखक गैर-आंतरिक फ़ंक्शन के साथ ठीक है अगर इसे निजी चिह्नित किया जा सकता है। इसलिए, इस सम्मेलन को जानना उपयोगी है। – orip

11

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

ध्यान दें कि आंतरिक कार्य एक साधारण कार्य नहीं है, यह एक बंद है। इस मामले पर विचार करें:

def outer(a): 
    b = compute_something_from(a) 
    def inner(): 
     do_something_with(a, b) 

यह मानक परीक्षण योग्यता व्यापार-बंद है। यदि आपका cyclomatic complexity बहुत अधिक है, तो आपके परीक्षण बहुत अधिक होंगे।

1

मुझे नहीं लगता कि बाहरी नामस्थान से आंतरिक() तक पहुंचने का कोई मौका है।

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

+0

मुझे विश्वास है कि cpython में आंतरिक समारोह का उपयोग करना संभव है। नीचे एक जवाब है जो दिखाता है कि यह कैसे करना है। – Aditya369

2

बाहरी फ़ंक्शन ऑब्जेक्ट से आंतरिक फ़ंक्शन प्राप्त करने का कोई तरीका नहीं (अन्य उत्तरों देखें!)। फिर भी दोनों यूनिट परीक्षण और बंदियां (मेरे लिए कम से कम) अद्भुत डेवलपर प्रदर्शन सुधार किए हैं। क्या हम दोनों हो सकते हैं? क्या हम अलगाव में नेस्टेड कार्यों का परीक्षण कर सकते हैं?

आसानी से नहीं।

हालांकि, ऐसा लगता है कि पाइथन मॉड्यूल पार्सर, अस्थ, या टोकनेज़र के उपयोग के साथ ही कोड को पासा करने के लिए, आंतरिक कार्यों को निकालने (घोंसले के माध्यम से कुछ पथ) निकालने और परीक्षणों को राज्य से चलाने के लिए अनुमति देने की अनुमति मिल सकती है। अधिक-घोंसले कार्यों (परीक्षण लक्ष्य के भीतर परिभाषित) के लिए संलग्न कार्य (बंद-ओवर नामों के लिए मूल्य) और स्टब्स/मैक्स।

कोई भी इस तरह से कुछ जानता है? Googling कुछ भी खोजने में विफल रहा।

1

मुझे भी यही संदेह था और आंतरिक कार्यों के लिए परीक्षण करने का एक तरीका मिला।

def outer(): 
    def inner(): 
     pass 

    if __debug__: 
     test_inner(inner) 
     # return 

def test_inner(f): 
    f() # this calls the inner function 

outer() 

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

python -O code.py 
1

मैं एक छोटे से सहायक मॉड्यूल जो की अनुमति देता है लिखा है वास्तव में यह: नेस्टेड कार्यों का

उदाहरण:

def f(v1): 
    v2 = 1 
    def g(v3=2): 
    return v1 + v2 + v3 + 4 
    def h(): 
    return 16 
    return g() + h() + 32 

class C(object): 
    def foo(self): 
    def k(x): 
     return [ self, x ] 
    return k(3) 

def m(): 
    vm = 1 
    def n(an=2): 
    vn = 4 
    def o(ao=8): 
     vo = 16 
     return vm + an + vn + ao + vo 
    return o() 
    return n() 

import unittest 
from nested import nested 

class TestNested(unittest.TestCase): 
    def runTest(self): 
    nestedG = nested(f, 'g', v1=8, v2=1) 
    self.assertEqual(nestedG(2), 15) 
    nestedH = nested(f, 'h') 
    self.assertEqual(nestedH(), 16) 
    nestedK = nested(C.foo, 'k', self='mock') 
    self.assertEqual(nestedK(5), [ 'mock', 5 ]) 
    nestedN = nested(m, 'n', vm=1) 
    nestedO = nested(nestedN, 'o', vm=1, an=2, vn=4) 
    self.assertEqual(nestedO(8), 31) 

def main(argv): 
    unittest.main() 

if __name__ == '__main__': 
    import sys 
    sys.exit(main(sys.argv)) 
:

ये इकाई हो सकता है कोड के इस प्रकार का उपयोग कर परीक्षण किया 363,210

छोटे सहायक मॉड्यूल nested इस तरह दिखता है:

import types 

def freeVar(val): 
    def nested(): 
    return val 
    return nested.__closure__[0] 

def nested(outer, innerName, **freeVars): 
    if isinstance(outer, (types.FunctionType, types.MethodType)): 
    outer = outer.func_code 
    for const in outer.co_consts: 
    if isinstance(const, types.CodeType) and const.co_name == innerName: 
     return types.FunctionType(const, globals(), None, None, tuple(
      freeVar(freeVars[name]) for name in const.co_freevars))