PyTest teardown_class 运行 太早了

PyTest teardown_class is being run too soon

Python "teardown_class" 的行为与我预期的不一样。以下是我的代码摘要:

@classmethod
def setup_class(cls):
    cls.create_table(table1)
    cls.create_table(table2)
    cls.create_table(table3)

@classmethod
def create_table(cls, some_arg_here):
    """Some code here that creates the table"""

def test_foo(self):
    """Some test code here"""

@classmethod
def teardown_class(cls):
    """Perform teardown things"""

我相信它的执行方式是:

  1. create_table 正在使用第一个参数 (table1)
  2. 从设置中调用
  3. create_table 中的代码执行
  4. teardown_class 中的代码执行
  5. 上面的1-3用第二个参数
  6. 再次执行
  7. 上面的1-3用第3个参数再次执行
  8. test_foo 中的代码执行

我期望它的表现如何:

  1. create_table 使用第一个参数 (table1)
  2. 调用
  3. create_table 中的代码执行
  4. create_table 使用第二个参数调用 (table 2)
  5. create_table 中的代码执行
  6. create_table 使用第三个参数调用 (table 3)
  7. create_table 中的代码执行
  8. test_foo 中的代码执行
  9. teardown_class 中的代码执行

Python 2.7.10, pytest-3.6.2, py-1.5.3, pluggy-0.6.0

您的类方法缺少 cls 参数:

@classmethod
def create_table(some_arg_here):
    """Some code here that creates the table"""

改为

@classmethod
    def create_table(cls, some_arg_here):

我修改了您的代码并添加了一些打印件:

class TestClass:

    @classmethod
    def setup_class(cls):
        print("Setting up")
        cls.create_table('table1')
        cls.create_table('table2')
        cls.create_table('table3')

    @classmethod
    def create_table(cls, some_arg_here):
        print("Creating:", some_arg_here)
        """Some code here that creates the table"""

    def test_foo(self):
        print('Running test_foo')
        """Some test code here"""

    @classmethod
    def teardown_class(cls):
        print("Tearing down")
        """Perform teardown things"""

如果你 运行 它与 -s 你会得到以下结果:

test.py Setting up
Creating: table1
Creating: table2
Creating: table3
Running test_foo
.Tearing down

如您所见,一切都按预期进行。调用 setup_class,创建表(全部 3 个),测试方法 运行,然后 teardown_class 开始。

如果你添加一个函数 test_bar() 你会得到:

test.py Setting up
Creating: table1
Creating: table2
Creating: table3
Running test_foo
.Running test_bar
.Tearing down

对我来说似乎也很好..

您是否有更多关于您的假设错误的提示?

我找到了解决方案。我在 setup 函数内部将 create_table 函数重新创建为 inner 函数。

@classmethod
def setup_class(cls):
    def create_table(some_arg_here):
       """Some code here that creates the table"""

    create_table(table1)
    create_table(table2)
    create_table(table3)

def test_foo(self):
    """Some test code here"""

@classmethod
def teardown_class(cls):
    """Perform teardown things"""

现在 运行 如我所料,顺序如下:

  1. 运行 create_table table1 参数一次
  2. 运行 create_table table2 参数一次
  3. 运行 create_table table3 参数一次
  4. 运行 test_foo
  5. 运行 teardown_class

似乎 any/every 时间从 setup 调用了 setup 之外的函数,它导致 teardown 函数 运行 直接在 外部函数 运行 中的代码之后,这就是我面临的问题。