Repository navigation
Replies: 1 comment
|
Hi @mikicz Yes. The native pytest solution is to make the parameter class-scoped and make the dependent fixture class-scoped as well: import pytest
@pytest.mark.parametrize(
"variant",
["a", "b"],
scope="class",
)
class TestSomething:
@pytest.fixture(scope="class", autouse=True)
def some_fixture(self, variant):
obj = create_object_in_database(variant)
yield obj
delete_object_from_database(obj)
def test_1(self, some_fixture):
pass
def test_2(self, some_fixture):
passCurrent pytest uses the parametrization scope to group tests by parameter instance, so the effective lifecycle is: In other words, you do not need to generate subclasses yourself for this. The important part is the teardown. If your fixture only does: @pytest.fixture(scope="class")
def some_fixture(variant):
create_object_in_database(variant)then changing fixture instances does not magically remove the previous database object. The external side effect remains, which can make it look as though both parametrizations are "active". Use a @pytest.fixture(scope="class")
def some_fixture(variant):
obj = create_object_in_database(variant)
yield obj
delete_object_from_database(obj)Pytest's fixture machinery only caches one instance of a parametrized fixture at a time, and class-scoped parametrization is specifically used to group the tests belonging to the same parameter value. So your desired behavior is supported natively; the combination is: @pytest.mark.parametrize(..., scope="class")plus: @pytest.fixture(scope="class")with proper teardown of any external resources created by the fixture. Please mark this answer as accepted if it helped, thank you. |
Uh oh!
There was an error while loading. Please reload this page.
Hello, I've got a question about class parametrisation. I'm looking for a pytest native way to parametrize a test class with a class-scoped fixture, which doesn't make fixture exist multiple times at once with each of the parameters.
The code examples are also stored in this repo with all imports: https://github.com/mikicz/symmetrical-engine
Setup
Let's say I've got some test where class-based fixture is used to make the test faster, something like this. The fixture
some_fixturegenerates and inserts some object into the database, and it takes a while, let's say ten seconds. The whole class therefore takes 10 seconds to run, as thesome_fixturefixture gets reused for the two tests.Test output
Now, let's say the code I'm testing has changed and there's two variants and I want to test both using the same test, just with some parameter. The obvious to do this is to use
pytest.mark.parametrize("variant", ["a", "b"])on the class. The trouble now starts. By default, this adds avariantfixture to the class with function scope. This means, that I need to remove class scope fromsome_fixture, which makes the test twice as slow. But at least it will work fine in most cases.Test output
There's an option to add a
scope="class"parameter to thepytest.mark.parametrize, which makesvarianta class-scope fixture. This does however break the tests if the tests assume that there's only one object in the database created bysome_fixture.Desired behaviour
What I would like to do is to run the whole
TestSomethingwith each of the variants, but not such that thesome_fixturefixture being available in the scope at the same time with each of the variants, basically make it safe for the test to still assume that there's only one object in the database.Attempted solutions
Base Class
One solution is to define a base class for the tests, and then subclass for each of the variants, something like this:
Test output
This does work, but there's downsides:
variantas a fixture, but to use the propertyCursed Metaprogramming
I did develop a way to basically automate the subclass approach, but it's quite ugly metaprogramming:
Test output
So this solves the two issues I have with the base class approach, but it's not the prettiest solution.
Conclusion
So the question I have is, is there a native pytest way to do what I did in the attempted solutions?
All reactions