2012-09-28 12 views
8

मैं कठिनाइयों परीक्षण अजगर कार्यों है कि एक iterable लौट , कार्य हैं ऐसे ही आ रही है में iterable लौटने परीक्षण कार्यों उपज या कार्यों कि बस, एक iterable लौट return imap(f, some_iter) या return permutations([1,2,3]) की तरह।अजगर

तो क्रमिक उदाहरण के साथ, मुझे उम्मीद है कि फ़ंक्शन का आउटपुट [(1, 2, 3), (1, 3, 2), ...] होगा। तो, मैं अपने कोड का परीक्षण करना शुरू करता हूं।

def perm3(): 
    return permutations([1,2,3]) 

# Lets ignore test framework and such details 
def test_perm3(): 
    assertEqual(perm3(), [(1, 2, 3), (1, 3, 2), ...]) 

यह काम नहीं करेगा, perm3() के बाद से एक iterable, नहीं एक सूची है। तो हम इस विशेष उदाहरण को ठीक कर सकते हैं।

def test_perm3(): 
    assertEqual(list(perm3()), [(1, 2, 3), (1, 3, 2), ...]) 

और यह ठीक काम करता है। लेकिन क्या होगा यदि मैंने पुनरावृत्तियों को घोंसला दिया है? यह पुनरावृत्तियों उपज है? अभिव्यक्तियों की तरह product(permutations([1, 2]), permutations([3, 4])) कहें। अब यह शायद उपयोगी नहीं है लेकिन यह स्पष्ट है कि यह होगा ( इटरेटर को अनलोल करने के बाद) [((1, 2), (3, 4)), ((1, 2), (4, 3)), ...] जैसे कुछ। हालांकि, हम अपने परिणाम के आस-पास list को लपेट नहीं सकते हैं, क्योंकि यह केवल iterable<blah> से [iterable<blah>, iterable<blah>, ...] पर बदल जाएगा। खैर निश्चित रूप से मैं map(list, product(...)) कर सकते हैं, लेकिन 2.

तो की एक नेस्टिंग स्तर के लिए यह केवल काम करता है, अजगर परीक्षण समुदाय समस्याओं के लिए किसी भी समाधान है जब iterables परीक्षण? स्वाभाविक रूप से कुछ पुनरावृत्तियों इस तरह से परीक्षण नहीं किए जा सकते हैं, जैसे कि आप एक अनंत जनरेटर चाहते हैं, लेकिन अभी भी इस मुद्दे को किसी के लिए सोचा जाना आम बात होनी चाहिए।

उत्तर

4

मैं KennyTM's assertRecursiveEq का उपयोग करें:

import unittest 
import collections 
import itertools 

class TestCase(unittest.TestCase): 
    def assertRecursiveEq(self, first, second, *args, **kwargs): 
     """ 
     https://stackoverflow.com/a/3124155/190597 (KennyTM) 
     """ 
     if (isinstance(first, collections.Iterable) 
      and isinstance(second, collections.Iterable)): 
      for first_, second_ in itertools.izip_longest(
        first, second, fillvalue = object()): 
       self.assertRecursiveEq(first_, second_, *args, **kwargs) 
     else: 
      # If first = np.nan and second = np.nan, I want them to 
      # compare equal. np.isnan raises TypeErrors on some inputs, 
      # so I use `first != first` as a proxy. I avoid dependency on numpy 
      # as a bonus. 
      if not (first != first and second != second): 
       self.assertAlmostEqual(first, second, *args, **kwargs)     

def perm3(): 
    return itertools.permutations([1,2,3]) 

class Test(TestCase): 
    def test_perm3(self): 
     self.assertRecursiveEq(perm3(), 
      [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]) 

if __name__ == '__main__': 
    import sys 
    sys.argv.insert(1, '--verbose') 
    unittest.main(argv = sys.argv) 
+0

मैं इसे स्वीकार करूंगा क्योंकि यह डीबीडब्ल्यू के जवाब के जितना अच्छा है। मेरे उत्तर के विपरीत आप 'tuples'/'सूचियों' को मिला सकते हैं। यह उत्तर सिर्फ कॉपी-पेस्ट रननेबल है। :) परंतु! यदि कोई जवाब था तो मैं अधिक संतुष्ट होगा जहां आप (1) वास्तव में जांचते हैं कि यह एक पुनरावर्तनीय लौटाता है ('वापसी' परमिट ([1,2,3]) ''वापसी सूची (क्रमपरिवर्तन ([1,2,3 ])) '** और ** (2) पास नहीं होना चाहिए, नेस्टेड अपेक्षित मूल्य में सही प्रकार होना चाहिए। यह एक सूची में टुपल्स में से एक को बदलना नहीं चाहिए (बदलना' (2, 3, 1) '' [2, 3, 1] ') – Tarrasch

+0

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

0

मैं किसी भी मानक तरीका अजगर प्रोग्रामर iterables परीक्षण के बारे में पता नहीं है, लेकिन आप बस एक पुनरावर्ती समारोह nestedness के किसी भी स्तर के लिए काम में map और list के अपने विचार लागू कर सकते हैं।

def unroll(item): 
    if "__iter__" in dir(item): 
    return map(unroll, item) 
    else: 
    return item 

तब आपका परीक्षण वास्तव में काम करेगा।

def test_product_perms(): 
    got = unroll(product(...)) 
    expected = [[[1, 2], [3, 4]], [[1, 2], [4, 3]], ...] 
    assertEqual(got, expected) 

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

इस निष्पक्ष दृष्टिकोण के साथ एक और समस्या यह है कि पासिंग टेस्ट का मतलब नहीं है जो फ़ंक्शन काम करता है। मान लें कि आप assertEqual(list(my_fun()), [1, 2, 3]) जांचते हैं, जबकि आपको लगता है कि यह एक पुनरावर्तनीय लौटा सकता है कि जब "सूचीबद्ध" [1, 2, 3] के बराबर है। ऐसा हो सकता है कि यह चाहता था कि यह एक पुनरावृत्ति वापस नहीं लौटा, यह शायद एक सूची या एक टुपल वापस आ गया हो!

1

आप type (जो आपको सूचियों, tuples, आदि के बीच अंतर करने की अनुमति दे रहा था) शामिल करने के लिए सुझाव का विस्तार कर सकते हैं।), इसलिए जैसे:

def unroll(item): 
    if "__iter__" in dir(item): 
    return map(unroll, item), type(item) 
    else: 
    return item, type(item) 

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

got = unroll(permutations([1,2])) 
([([(1, <type 'int'>), (2, <type 'int'>)], <type 'tuple'>), ([(2, <type 'int'>), (1, <type 'int'>)], <type 'tuple'>)], <type 'itertools.permutations'>) 
# note the final: <type 'itertools.permutations'> 
expected = [(1, 2), (2, 1)] 
assertEqual(x[0], unroll(expected)) # check underlying 
assertEqual(x[1], type(permutations([])) # check type 

उल्लेख करने की एक बात, typeऑब्जेक्ट्स के बीच अंतर करने में मोटे है। <type 'classobj'> ...

+1

मैं 'पसंद करेंगे isinstance()' 'प्रकार के ऊपर()'। –

+0

@ अश्विनी चौधरी मैं सोच रहा था क्योंकि मैंने पोस्ट/बाएं काम किया था, एक बेहतर तरीका था :) –

2

1. परिणामों का क्रम कोई फर्क नहीं पड़ता अगर

उपयोग unittest.assertItemsEqual()। यह परीक्षण करता है कि आइटम स्वयं और संदर्भ दोनों में मौजूद हैं, लेकिन आदेश को अनदेखा करते हैं। यह आपके उदाहरण पर एक घोंसला वाला गहरा उदाहरण है। यह एक 2-गहरे उदाहरण पर भी काम करता है जिसे मैंने समझाया।

2. परिणामों का क्रम मायने रखती हैं

मैंने कभी perm3() एक सूची के परिणामों कास्टिंग नहीं सुझाव है। इसके बजाए, तत्वों की तुलना सीधे करें जैसा कि आप पुनरावृत्त करते हैं। यहां एक परीक्षण कार्य है जो आपके उदाहरण के लिए काम करेगा। मैं इसे unittest.TestCase का एक उपवर्ग को जोड़ा गया:

def assertEqualIterables(self, itable1, itable2): 
    for ival1, ival2 in zip(itable1, itable2): 
     if "__iter__" in dir(ival1): 
      self.assertEqualIterables(ival1, ival2) 
     else: 
      self.assertEquals(ival1, ival2) 

इसे पसंद का प्रयोग करें:

def test_perm3(self): 
    reference = [((1, 2), (3, 4)), ((1, 2), (4, 3)), 
       ((2, 1), (3, 4)), ((2, 1), (4, 3)),] 

    self.assertEqualIterables(perm3(), reference) 
+0

क्या किसी और ने जोर दिया है कि इटेटर्स के कई गहरे घोंसले पर काम कर रहे हैं? मैं वास्तव में काम करने की उम्मीद नहीं कर रहा था ... क्या मैं पागल हूं? – dbn