2
votes

I am working with a code base which which is mostly written with unittest. The tests are run with pytest. I am trying to simplify the tests by parameterizing some of them. To work towards this goal, I am trying to learn how to use pytest fixtures and refactor some of the existing unittest-based tests. The current tests have a global fixture in conftest.py:

@pytest.fixture(autouse=True)
def register_cleanup():
    yield True
    print("cleaning up database")

Now I want to add a fixture which is specific to one of my test modules, something along the lines of

@pytest.fixture()
def foo_fixture():
    print("setup fixture")
    yield
    print("tear down fixture")


class Foo(unittest.TestCase):
    def setUp(self):
        print('unittest setUp()')

    def test(self):
        print('test')

However, the print() statements in this module fixture never execute. As an intermediate step, I am keeping the unittest-based structure and adding to it. Is it possible to get this working the way I want or do I need to scrap unittest altogether and go directly to pytest.

2
Where would you expect this fixture to be used? Did you want to turn on autouse=True here as well? In general, fixtures are only executed when they are a parameter to the test, and are less of generic cleanup mechanisms than scoped assumptionsCireo
@Cireo Do you mean I should add autouse=True to foo_fixture() similarly to register_cleanup()?Code-Apprentice
@Cireo Feel free to post this as an answer.Code-Apprentice

2 Answers

1
votes

You'll want to mark it:

@pytest.mark.usefixtures("foo_fixture")
class Foo(unittest.TestCase):
    ...

Note: you may have more than one conftest.py. Put the more specific fixture into this test subdirectory's conftest.py.

0
votes

Where would you expect this fixture to be used?

Did you want to turn on autouse=True here as well? In general, fixtures are only executed when they are a parameter to the test, and are less of generic cleanup mechanisms than scoped assumptions. By turning on autouse for this fixture you will essentially add an extra setup-cleanup step for the current module:

https://docs.pytest.org/en/latest/fixture.html#autouse-fixtures-xunit-setup-on-steroids

Here is how autouse fixtures work in other scopes:

autouse fixtures obey the scope= keyword-argument: if an autouse fixture has scope='session' it will only be run once, no matter where it is defined. scope='class' means it will be run once per class, etc. if an autouse fixture is defined in a test module, all its test functions automatically use it. if an autouse fixture is defined in a conftest.py file then all tests in all test modules below its directory will invoke the fixture. lastly, and please use that with care: if you define an autouse fixture in a plugin, it will be invoked for all tests in all projects where the plugin is installed. This can be useful if a fixture only anyway works in the presence of certain settings e. g. in the ini-file. Such a global fixture should always quickly determine if it should do any work and avoid otherwise expensive imports or computation.

[Adaptied comment into an answer]