我想知道,当为具有多重继承的类运行setUp()
/tearDown()
方法时,unittest
做了什么特别的事情。
举以下例子:
import unittest
class Foo:
def __init__(self, foo):
self._foo = foo
@property
def foo(self):
return self._foo
class TestsBase(unittest.TestCase):
def setUp(self):
super().setUp()
self.base_value = 1
class TestsMixin:
def setUp(self):
super().setUp()
self.expected_value = 1
class TestCase1(TestsMixin, TestsBase):
def test_base_value_is_equal_to_expected_value(self):
foo = Foo(self.base_value)
self.assertEqual(foo.foo, self.expected_value)
class TestCase2(TestsBase, TestsMixin):
def test_base_value_is_equal_to_expected_value(self):
foo = Foo(self.base_value)
self.assertEqual(foo.foo, self.expected_value)
if __name__ == '__main__':
unittest.main()
当运行此代码时,TestCase1
类测试将成功,而TestCase2
测试将失败,说明AttributeError: 'TestCase2' object has no attribute 'expected_value'
。
现在,我明白了MRO是如何工作的,我也明白了为什么会出现这个错误,但让我困惑的是,为什么TestCase1
没有同样的问题?毕竟,难道不应该使用TestsMixin
中的setUp()
方法,跳过TestsBase
中的setUp()
吗?
我的结论是unittest
模块必须为此做些什么。有人知道什么/怎么做吗?
提前谢谢。
我找到了自己问题的答案。最后,一切都归结为MRO。
例如,MRO看起来是这样的:
对于测试用例1:
- TestCase1
- TestsMixin
- TestsBase
- unittest.TestCase
- object
对于测试用例2:
- TestCase2
- TestsBase
- unittest.TestCase
- TestsMixin
- object
问题是,unittest.TestCase
在其自己的setUp()
调用中不调用super().setUp()
。
原因很简单,object
没有setUp()
。
在unittest.TestCase()
中,通过在其setUp()
例程中添加以下代码,可以很容易地绕过这一点:
def setUp(self):
parent = super()
if hasattr(parent, 'setUp'):
parent.setUp()
它是有效的。但这说明了另一个问题。现在,我的TestsMixin
停止为工作,原因完全相同。我必须在每一个可能的mixin中添加这个保护代码,这并不理想。
因此,更好的解决方案是保持原样,并确保在您的基础之前列出您的mixin。