PyTest teardown_class is being run too soon

☆樱花仙子☆ 提交于 2021-01-29 14:23:57

问题


The Python "teardown_class" is not behaving as I expect it to. Below is a summary of my code:

@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"""

I believe the way it is executing is that:

  1. create_table is being called from setup with 1st parameter (table1)
  2. Code in create_table executes
  3. Code in teardown_class executes
  4. 1-3 above is executed again with the 2nd parameter
  5. 1-3 above is executed again with the 3rd parameter
  6. Code in test_foo executes

How I expect it to perform:

  1. create_table is called with 1st parameter (table1)
  2. Code in create_table executes
  3. create_table is called with 2nd parameter (table 2)
  4. Code in create_table executes
  5. create_table is called with 3rd parameter (table 3)
  6. Code in create_table executes
  7. Code in test_foo executes
  8. Code in teardown_class executes

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


回答1:


Your classmethod misses the cls param:

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

Change it to

@classmethod
    def create_table(cls, some_arg_here):

I modified your code and added some prints:

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"""

If you run it with -s you will get the following result:

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

As you can see, everything works as expected. The setup_class is called, tables are created (all 3), test method runs and then teardown_class kicks in.

If you add a function test_bar() you will get:

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

Seems also to be fine to me..

Do you have some more hints for your assumption something is wrong?




回答2:


I was able to find the solution. I recreated the create_table function as an inner function, inside of the setup function.

@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"""

And now it runs as I expect it to, in this sequence:

  1. Run create_table once for table1 param
  2. Run create_table once for table2 param
  3. Run create_table once for table3 param
  4. Run test_foo
  5. Run teardown_class

It seems that any/every time a function that is outside of setup is called from setup, it causes the teardown function to run directly after the code in the outer function runs, and that was the issue I was facing.



来源:https://stackoverflow.com/questions/51070275/pytest-teardown-class-is-being-run-too-soon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!