subclassing unittest.TestCase,为`super()__ init __()`提供关键字args并获取`__init__得到一个意外的关键字参数

时间:2016-04-13 01:14:04

标签: python-2.7 inheritance super python-unittest

我试图使用unittest.TestCase组成一个类层次结构。这些都不是严格单元测试我在这里运行,我试图改为测试一堆依赖于几个参数的字符串解析功能(客户 - 例如名称和缺失值)。一般的想法是简单地利用一些单元测试的便利性并保持干燥。

import unittest
import parsingfunc as i

class CustomerTestCase(unittest.TestCase):
    """Base class, most general functionality and test cases"""

    def __init__(self, testname):
        super(CustomerTestCase, self).__init__(testname)

    # helpers

    def mess_with_spaces():
        ...

    def mess_with_case(): 
        ...

    # tests

    def test_case(self, value):
        """
        Test that parsing function produces the same
        value regardless of case of input
        """
        self.assertEqual(self.func(value, missing=self.missing, customer=self.name), 
                         self.func(self.mess_with_case(value), missing=self.missing, customer=self.name)))
        ...

    def test_spaces(self, value):
        """
        Test that parsing function produces the same
        value regardless of spacing present in input
        """
        ...


class AisleValues(CustomerTestCase):
    """Base class for testing aisle values"""

    def __init__(self, testname, customername=None, missing=None):
        super(CustomerTestCase, self).__init__(testname)
        self.name = customername
        self.missing = missing
        self.func = i.aisle_to_num

    ...

class PeacockAisles(AisleValues):
    """Peacock aisle parsing test cases"""

    def __init__(self, testname):
        super(AisleValues, self).__init__(testname, customername='peacock', missing='nan')

    ...

现在尝试创建这些类的实例

In [6]: a = i.CustomerTestCase('space_test')

In [7]: a.__dict__
Out[7]: 
{'_cleanups': [],
 '_resultForDoCleanups': None,
 '_testMethodDoc': '\n        Test that parsing function produces the same\n        value regardless of spacing present in input\n        ',
 '_testMethodName': 'test_spaces',
 '_type_equality_funcs': {list: 'assertListEqual',
  dict: 'assertDictEqual',
  set: 'assertSetEqual',
  frozenset: 'assertSetEqual',
  tuple: 'assertTupleEqual',
  unicode: 'assertMultiLineEqual'}}

In [8]: b = i.AisleValues('test_spaces')

In [9]: b.__dict__
Out[9]: 
{'_cleanups': [],
 '_resultForDoCleanups': None,
 '_testMethodDoc': '\n        Test that parsing function produces the same\n        value regardless of spacing present in input\n        ',
 '_testMethodName': 'test_spaces',
 '_type_equality_funcs': {list: 'assertListEqual',
  dict: 'assertDictEqual',
  set: 'assertSetEqual',
  frozenset: 'assertSetEqual',
  tuple: 'assertTupleEqual',
  unicode: 'assertMultiLineEqual'},
 'func': <function integration.aisle_to_num>,
 'missing': None,
 'name': None}

In [10]: b = i.AisleValues('test_spaces', customername='peacock', missing='nan')

In [11]: b.__dict__
Out[12]: 
{'_cleanups': [],
 '_resultForDoCleanups': None,
 '_testMethodDoc': '\n        Test that parsing function produces the same\n        value regardless of spacing present in input\n        ',
 '_testMethodName': 'test_spaces',
 '_type_equality_funcs': {list: 'assertListEqual',
  dict: 'assertDictEqual',
  set: 'assertSetEqual',
  frozenset: 'assertSetEqual',
  tuple: 'assertTupleEqual',
  unicode: 'assertMultiLineEqual'},
 'func': <function integration.aisle_to_num>,
 'missing': 'nan',
 'name': 'peacock'}

In [13]: c = i.PeacockAisles('test_spaces')

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-d4bba181b94e> in <module>()
----> 1 c = i.PeacockAisles('test_spaces')

/path/to/python.py in __init__(self, testname)
     89 
     90     def __init__(self, testname):
---> 91         super(AisleValues, self).__init__(testname, customername='peacock', missing='nan')
     92         pprint(self.__dict__)
     93 

TypeError: __init__() got an unexpected keyword argument 'customername'

那么这笔交易是什么?谢谢!

1 个答案:

答案 0 :(得分:1)

您未正确拨打super。当你在super调用中命名一个类时,它应该是当前类,而不是基类(除非你真的知道你正在做什么而你想跳过它基类的实现,也支持祖父母和#34;类。

您当前的代码AisleValues.__init__呼叫unittest.TestCase.__init__,绕过CustomerTestCase.__init__。它恰好起作用,因为CustomerTestCase.__init__没有做任何有用的事情(你可以删除它而没有任何效果),但这只是运气。当PeacockAisles.__init__调用CustomerTestCase.__init__(绕过AisleValues.__init__)时,它会失败,因为祖父母类不允许所有与其子项相同的参数。

你想:

class AisleValues(CustomerTestCase):
    """Base class for testing aisle values"""

    def __init__(self, testname, customername=None, missing=None):
        super(AisleValues, self).__init__(testname)            # change the class named here
        ...

class PeacockAisles(AisleValues):
    """Peacock aisle parsing test cases"""

    def __init__(self, testname):
        super(PeacockAisles, self).__init__(testname, customername='peacock', missing='nan')
        ...                                             # and on the previous line