Skip to content

Allow fixtures to explicitly state which other fixtures they invalidate #4477

@SalmonMode

Description

@SalmonMode

Regarding the discussion on #3905, I'm making a new issue to target with a PR, as I don't think this would be considered a solution to the original issue.

In order to keep the logic of a test suite's fixtures straightforward and to avoid possibly having to repeat operations unnecessarily, I propose we add a new optional argument (invalidates) to pytest.fixture and pytest.mark.parametrize that allows them to specify what fixture should be considered invalid once they run, and should be finalized when the invalidating fixture is finalized.

Here's a quick example (pulled from the discussion in #3905):

@pytest.fixture(scope="class", autouse=True)
def page(driver):
    """Goes to and returns a page object for the page with a form on it."""
    driver.get("https://mysite.com/some_form")
    return FormPage(driver)

class TestDefault():

    # tests for the default state of the page

class TestBlankSubmit():
    @pytest.fixture(scope="class", autouse=True)
    def submit_form(self, page):
        page.form.submit()

    # tests for the blank submit state of the page

class TestBadDataEntry():
    @pytest.fixture(
        scope="class",
        params=["bad_data1", "bad_data2"],
        autouse=True,
        invalidates="page",
    )
    def submit_bad_data(request, page):
        page.form.data = request.param
        page.form.submit()

    # tests for the bad data entry state of the page

Normally, in this example, TestBadDataEntry could probably not be trusted, because page would only happen once for the 1st param set, but it would not happen a 2nd time for the 2nd param set, which would mean that the 2nd param set would likely not be starting off from the same point as the 1st param set. In order to fix this, you'd have to define another page fixture just for that class and custom tailor it to make sure it happens once per param set, but this would mean writing duplicate code, and making things more complicated than they need to be.

But with the invalidates argument, each time submit_bad_data is finalized, it makes sure page is finalized as well, and when the fixtures of the 2nd param set request page, it will be executed again, resetting the state of the page.

I would also make it so that invalidates accepts one or more fixtures much like how similar arguments are provided, i.e. either a list/tuple of strings of fixture names (e.g. ["fixture_a", "fixture_b"]), or a comma separated string of fixture names (e.g. "fixture_a,fixture_b").

edit: added autouse to page fixture

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: fixturesanything involving fixtures directly or indirectlytype: proposalproposal for a new feature, often to gather opinions or design the API around the new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions