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。