Python unittest.TestCase 执行顺序

96 投票
11 回答
81828 浏览
提问于 2025-04-16 14:10

在Python的unittest中,有没有办法设置测试用例的执行顺序呢?

在我现在的TestCase类里,有些测试用例会产生一些影响,这些影响会影响到其他测试用例的正常运行。现在我意识到,正确的做法是使用setUp()来处理所有的准备工作,但我想实现一种设计,让每个后续的测试都能稍微增加一些状态,以便下一个测试可以使用。我觉得这样更优雅。

class MyTest(TestCase):

  def test_setup(self):
    # Do something

  def test_thing(self):
    # Do something that depends on test_setup()

理想情况下,我希望测试按照它们在类中出现的顺序来运行。但似乎它们是按照字母顺序来执行的。

11 个回答

29

来自 unittest — 单元测试框架,部分 组织测试代码

注意:各种测试的执行顺序是通过对测试方法名称进行排序来决定的,这个排序是基于字符串的内置顺序。

所以你只需要确保 test_setup 的名字是所有测试方法中字符串值最小的。

请注意,你不应该依赖这种行为——不同的测试函数应该是独立的,执行顺序不应该影响它们的结果。 如果你确实需要特定的执行顺序,可以参考上面 ngcohlan的回答

60

对于这样的期望,写一个整体的测试是个好习惯。不过,如果你像我一样有点搞笑的话,你可以简单地把方法按字母顺序写得不好看,这样它们就会按照从a到b的顺序排列,正如Python文档中提到的 - unittest — 单元测试框架

请注意,各个测试用例的运行顺序是通过对测试函数名称进行排序来决定的,这个排序是基于字符串的内置顺序。

示例

def test_a_first():
    print "1"
def test_b_next():
    print "2"
def test_c_last():
    print "3"
89

不要把它们当成独立的测试——如果你想要一个整体的测试,就写一个整体的测试。

class Monolithic(TestCase):
  def step1(self):
      ...

  def step2(self):
      ...

  def _steps(self):
    for name in dir(self): # dir() result is implicitly sorted
      if name.startswith("step"):
        yield name, getattr(self, name) 

  def test_steps(self):
    for name, step in self._steps():
      try:
        step()
      except Exception as e:
        self.fail("{} failed ({}: {})".format(step, type(e), e))

如果测试之后出现失败,并且你想知道所有失败的步骤,而不是在第一个失败的步骤就停止测试,你可以使用 subtests 功能:https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests

(对于 Python 3.4 之前的版本,可以通过 unittest2 使用 subtest 功能:https://pypi.python.org/pypi/unittest2

撰写回答