[TIP] pytest: Setup/TearDown with fixtures

Laszlo Papp lpapp at kde.org
Fri Sep 5 07:42:54 PDT 2014


On Wed, Sep 3, 2014 at 9:08 PM, Floris Bruynooghe <flub at devork.be> wrote:
> Hello Laszlo,
>
> All that follows is my personal opinion and may not be official best
> practices.  Furthermore there are multiple ways to achieve this, what
> you did clearly already worked.  Anyway, here goes:
>
> On 2 September 2014 14:58, Laszlo Papp <lpapp at kde.org> wrote:
>> Right, I think this could be added to the official documentation to
>> have a copy/pasteable example in there:
>>
>> class TestFoo:
>>     @classmethod
>>     @pytest.fixture(scope="class", autouse = True)
>>     def setup(self, request):
>>         self.session = foo.session()
>>         def tearDown():
>>             session.logout()
>>         request.addfinalizer(tearDown)
>>
>> I am yet to test this in practice, but this simple snippet would have
>> been a timer-saver for me when writing this basic functionality ...
>
> There are 2 main issues I have with this example:
>
> 1) I actively avoid using fixture names which conflict with the xUnix
> or nose setup/teardown compatibility names to avoid confusion.
>
> 2) When using fixtures I treat the class purely as a container
> providing structure, kind of like a module.  So storing state on the
> class/instance is right out.  The power of fixtures comes explicitly
> from decoupling test class instances from fixture issues
> (setup/teardown) which makes fixtures much more composable due to
> better separation of concerns.  This is IMHO where the power of
> fixtures comes from.
>
> With that said I would write your example as:
>
> class TestFoo:
>
>     @pytest.fixture(scope='class', autouse=True)
>     def session(self, request):
>         session = foo.session()
>         request.addfinalizer(session.logout)
>
>     def test_foo(self):
>         # test code not using the session explicitly,
>         # will still be created and logged out however.
>
>     def test_bar(self, session):
>         # test code using session explicitly.
>
> Structuring the tests like this makes it explicit what your tests are
> doing.  It may even transpire that all tests use the session in which
> case it this could be refactored to not be an autouse fixture.
>
> As a bonus this also avoids the confusion of class methods and their
> first argument (self? cls? Am I now assigning to the class or
> instance?).
>
>
> As for having a clearer example in the documentation as this being the
> equivalent in the documentation: it would be great if you could create
> a PR with this your original xUnit example and the fixture-based
> equivalent.  Then people after you will hopefully find the mental step
> to convert tests from this pattern more easily.

Thank you for your answer. In short, I think we will need to agree to
disagree :)

1) is personal style, and I just wished to be as consistent with the
rest of the world as possible to obtain the "smooth" transition that
you mentioned.

2) I am not sure. It is also a bit against being smooth, and it is
also easily becoming inconvenient when you use more than one class in
a test file which I personally occasionally do.

Thereby, I have not created a PR, but I have created a BR instead:
https://bitbucket.org/hpk42/pytest/issue/583

Personally, I would go for my original example if I can suggest
because I think that is the smoothest transition that does the same
what a "XUnit" user expects, yet based on fixtures. Having said that,
you guys are the maintainers, so I have probably little to no weight
here, rightfully.



More information about the testing-in-python mailing list