Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pytest fixture with scope "class" running on every method

Tags:

python

pytest

I'm trying to create a test environment with Pytest. The idea is to group test methods into classes.

For every class/group, I want to attach a config fixture that is going to be parametrized. So that I can run all the tests with "configuration A" and then all tests with "configuration B" and so on.

But also, I want a reset fixture, that can be executed before specific methods or all methods of a class.

The problem I have there is, once I apply my reset fixture (to a method or to a whole class), the config fixture seems to work in the function scope instead of the class scope. So, once I apply the reset fixture, the config fixture is called before/after every method in the class.

The following piece of code reproduces the problem:

import pytest
from pytest import *

@fixture(scope='class')
def config(request):
    print("\nconfiguring with %s" % request.param)
    yield
    print("\ncleaning up config")

@fixture(scope='function')
def reset():
    print("\nreseting")

@mark.parametrize("config", ["config-A", "config-B"], indirect=True)
#@mark.usefixtures("reset")
class TestMoreStuff(object):

    def test_a(self, config):
        pass

    def test_b(self, config):
        pass

    def test_c(self, config):
        pass

The test shows how the config fixture should work, being executed only once for the whole class. If you uncomment the usefixtures decoration, you can notice that the config fixture will be executed in every test method. Is it possible to use the reset fixture without triggering this behaviour?

like image 398
Gustavo Meira Avatar asked Nov 15 '17 16:11

Gustavo Meira


People also ask

How many times will a fixture of module scope run?

Fixtures with scope session will only be executed once per session. Every time you run pytest , it's considered to be one session. Scope session is designed for expensive operations like truncating table and loading a test set to the database.

What is pytest fixture scope =' function ')?

Software test fixtures initialize test functions. They provide a fixed baseline so that tests execute reliably and produce consistent, repeatable, results. Initialization may setup services, state, or other operating environments.

Can a class be a pytest fixture?

Like normal functions, fixtures also have scope and lifetime. The default scope of a pytest fixture is the function scope. Apart from the function scope, the other pytest fixture scopes are – module, class, and session.

Are pytest fixtures cached?

the fixture will be evaluated once per test session and the result will be cached and reused in all dependent tests.


Video Answer


1 Answers

As I mentioned in a comment, that seems to be a bug in Pytest 3.2.5.

There's a workaround, which is to "force" the scope of a parametrization. So, in this case if you include the scope="class" in the parametrize decorator, you get the desired behaviour.

import pytest
from pytest import *

@fixture(scope='class')
def config(request):
    print("\nconfiguring with %s" % request.param)
    yield
    print("\ncleaning up config")

@fixture(scope='function')
def reset():
    print("\nreseting")

@mark.parametrize("config", ["config-A", "config-B"], indirect=True, scope="class")
@mark.usefixtures("reset")
class TestMoreStuff(object):

    def test_a(self, config):
        pass

    def test_b(self, config):
        pass

    def test_c(self, config):
        pass
like image 111
Gustavo Meira Avatar answered Nov 03 '22 07:11

Gustavo Meira