子类化 unittest.TestCase,为 `super()__init__()` 提供关键字参数并得到 `__init__ 得到一个意外的关键字参数
Subclassing unittest.TestCase, providing keyword args to `super()__init__()` and getting `__init__ got an unexpected keyword argument
我正在尝试使用 unittest.TestCase 组成 class 层次结构。这些不是 strictly 单元测试我在这里 运行,我试图测试一堆依赖于一些参数的字符串解析功能(客户-name 和 missing-value 例如)。总体思路是简单地利用单元测试的一些便利并保持干燥。
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')
...
现在尝试创建这些 classes
的实例
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'
所以怎么回事?谢谢!
您没有正确调用 super
。当您在 super
调用中命名 class 时,它应该是 current class,而不是基础 class(除非您真的知道你在做什么,你也想跳过基础 class 的实现,转而使用 "grandparent" class).
您当前的代码有 AisleValues.__init__
调用 unittest.TestCase.__init__
,绕过 CustomerTestCase.__init__
。它恰好有效,因为 CustomerTestCase.__init__
没有做任何有用的事情(你可以删除它但没有任何效果),但这只是运气。当 PeacockAisles.__init__
调用 CustomerTestCase.__init__
(绕过 AisleValues.__init__
)时,它会失败,因为祖父母 class 不允许所有与它的 child.[=21 相同的参数=]
你想要:
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
我正在尝试使用 unittest.TestCase 组成 class 层次结构。这些不是 strictly 单元测试我在这里 运行,我试图测试一堆依赖于一些参数的字符串解析功能(客户-name 和 missing-value 例如)。总体思路是简单地利用单元测试的一些便利并保持干燥。
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')
...
现在尝试创建这些 classes
的实例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'
所以怎么回事?谢谢!
您没有正确调用 super
。当您在 super
调用中命名 class 时,它应该是 current class,而不是基础 class(除非您真的知道你在做什么,你也想跳过基础 class 的实现,转而使用 "grandparent" class).
您当前的代码有 AisleValues.__init__
调用 unittest.TestCase.__init__
,绕过 CustomerTestCase.__init__
。它恰好有效,因为 CustomerTestCase.__init__
没有做任何有用的事情(你可以删除它但没有任何效果),但这只是运气。当 PeacockAisles.__init__
调用 CustomerTestCase.__init__
(绕过 AisleValues.__init__
)时,它会失败,因为祖父母 class 不允许所有与它的 child.[=21 相同的参数=]
你想要:
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