TestCase和mixin类的setUp()/tearDown()方法的继承顺序

2024-06-24 11:54:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道unittest在为具有多重继承的类运行setUp()/tearDown()方法时做了什么特殊的事情

以以下为例:

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没有同样的问题?毕竟,不会使用来自TestsMixinsetUp()方法并跳过来自TestsBasesetUp()方法吗

我的结论是unittest模块必须做些什么才能让它工作。有人知道怎么做吗

提前谢谢


Tags: 方法selfbasefoovaluedefsetupunittest
1条回答
网友
1楼 · 发布于 2024-06-24 11:54:34

我已经找到了我自己问题的答案。最后,一切都归结于MRO

例如,MRO如下所示:

对于TestCase1:

 - TestCase1
 - TestsMixin
 - TestsBase
 - unittest.TestCase
 - object

对于TestCase2:

 - 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中添加这个保护代码,这并不理想

因此,更好的解决方案是保持原样,并确保在你的基础之前列出你的混音

相关问题 更多 >