TestCase 和 mixin 的 setUp()/tearDown() 方法的继承顺序 类
Order of inheritance for setUp()/tearDown() methods for TestCase and mixin classes
我想知道,当 运行 为具有多重继承的 classes 设置 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
class 测试将成功,而 TestCase2
测试将失败,表示 AttributeError: 'TestCase2' object has no attribute 'expected_value'
.
现在,我了解了 MRO 的工作原理,也了解了为什么显示此错误,但令我困惑的是,为什么 TestCase1
没有同样的问题?毕竟,不会使用 TestsMixin
中的 setUp()
方法并跳过 TestsBase
中的 setUp()
方法吗?
我的结论是 unittest
模块必须做一些事情才能使它起作用。有没有人有想法what/how?
提前致谢。
我找到了我自己问题的答案。最后,一切都归结为 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
因 完全相同的原因 停止工作。我将不得不在每个可能的混合中添加这个保护代码,这并不理想。
因此,更好的解决方案是保持原样,并确保在 之前 列出你的 mixins。
我想知道,当 运行 为具有多重继承的 classes 设置 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
class 测试将成功,而 TestCase2
测试将失败,表示 AttributeError: 'TestCase2' object has no attribute 'expected_value'
.
现在,我了解了 MRO 的工作原理,也了解了为什么显示此错误,但令我困惑的是,为什么 TestCase1
没有同样的问题?毕竟,不会使用 TestsMixin
中的 setUp()
方法并跳过 TestsBase
中的 setUp()
方法吗?
我的结论是 unittest
模块必须做一些事情才能使它起作用。有没有人有想法what/how?
提前致谢。
我找到了我自己问题的答案。最后,一切都归结为 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
因 完全相同的原因 停止工作。我将不得不在每个可能的混合中添加这个保护代码,这并不理想。
因此,更好的解决方案是保持原样,并确保在 之前 列出你的 mixins。