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?
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.
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.
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.
the fixture will be evaluated once per test session and the result will be cached and reused in all dependent tests.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With