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
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) topytest.fixtureandpytest.mark.parametrizethat 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):
Normally, in this example,
TestBadDataEntrycould probably not be trusted, becausepagewould 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 anotherpagefixture 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
invalidatesargument, each timesubmit_bad_datais finalized, it makes surepageis finalized as well, and when the fixtures of the 2nd param set requestpage, it will be executed again, resetting the state of the page.I would also make it so that
invalidatesaccepts 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
autousetopagefixture