From 6eb5de114f6b236401a5a625f8c6739af28ecfee Mon Sep 17 00:00:00 2001 From: Sebastian Cao Date: Thu, 18 Jun 2026 19:35:07 +0800 Subject: [PATCH] fix: keep multi-browser parametrization when the page fixture is overridden --- .../pytest_playwright.py | 13 ++++++++++ .../pytest_playwright/pytest_playwright.py | 13 ++++++++++ tests/test_asyncio.py | 25 +++++++++++++++++++ tests/test_sync.py | 25 +++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/pytest-playwright-asyncio/pytest_playwright_asyncio/pytest_playwright.py b/pytest-playwright-asyncio/pytest_playwright_asyncio/pytest_playwright.py index 50966c2..d3516c2 100644 --- a/pytest-playwright-asyncio/pytest_playwright_asyncio/pytest_playwright.py +++ b/pytest-playwright-asyncio/pytest_playwright_asyncio/pytest_playwright.py @@ -123,7 +123,20 @@ def pytest_runtest_call(item: Any) -> Generator[None, Any, None]: raise _BaseExceptionGroup("Soft assertion failures", errors) +# Fixtures defined by this plugin that (transitively) require a browser and +# therefore "browser_name". When one of them is requested through a user +# override of e.g. the "page" fixture, some pytest versions drop "browser_name" +# from the fixture closure, which would silently disable running the test +# against multiple browsers. +# https://github.com/microsoft/playwright-pytest/issues/172 +_BROWSER_FIXTURES = ("page", "context", "new_context", "browser", "browser_type") + + def pytest_generate_tests(metafunc: Any) -> None: + if "browser_name" not in metafunc.fixturenames and any( + name in metafunc.fixturenames for name in _BROWSER_FIXTURES + ): + metafunc.fixturenames.append("browser_name") if "browser_name" in metafunc.fixturenames: browsers = metafunc.config.option.browser or ["chromium"] metafunc.parametrize("browser_name", browsers, scope="session") diff --git a/pytest-playwright/pytest_playwright/pytest_playwright.py b/pytest-playwright/pytest_playwright/pytest_playwright.py index 119a535..5ac63e3 100644 --- a/pytest-playwright/pytest_playwright/pytest_playwright.py +++ b/pytest-playwright/pytest_playwright/pytest_playwright.py @@ -120,7 +120,20 @@ def pytest_runtest_call(item: Any) -> Generator[None, Any, None]: raise _BaseExceptionGroup("Soft assertion failures", errors) +# Fixtures defined by this plugin that (transitively) require a browser and +# therefore "browser_name". When one of them is requested through a user +# override of e.g. the "page" fixture, some pytest versions drop "browser_name" +# from the fixture closure, which would silently disable running the test +# against multiple browsers. +# https://github.com/microsoft/playwright-pytest/issues/172 +_BROWSER_FIXTURES = ("page", "context", "new_context", "browser", "browser_type") + + def pytest_generate_tests(metafunc: Any) -> None: + if "browser_name" not in metafunc.fixturenames and any( + name in metafunc.fixturenames for name in _BROWSER_FIXTURES + ): + metafunc.fixturenames.append("browser_name") if "browser_name" in metafunc.fixturenames: browsers = metafunc.config.option.browser or ["chromium"] metafunc.parametrize("browser_name", browsers, scope="session") diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index ac634c5..d31df06 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -175,6 +175,31 @@ async def test_multiple_browsers(page): result.assert_outcomes(passed=3) +def test_multiple_browsers_with_overridden_page_fixture( + testdir: pytest.Testdir, +) -> None: + # Overriding the "page" fixture must not disable running the test against + # each requested browser. + # https://github.com/microsoft/playwright-pytest/issues/172 + testdir.makepyfile( + """ + import pytest + + @pytest.fixture + def page(page): + yield page + + def test_a(page): + pass + """ + ) + result = testdir.runpytest( + "--collect-only", "-q", "--browser", "chromium", "--browser", "firefox" + ) + assert result.ret == 0 + result.stdout.fnmatch_lines(["*test_a*chromium*", "*test_a*firefox*"]) + + def test_browser_context_args(testdir: pytest.Testdir) -> None: testdir.makeconftest( """ diff --git a/tests/test_sync.py b/tests/test_sync.py index cfaf4c9..d6cd8f3 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -209,6 +209,31 @@ def test_multiple_browsers(page): result.assert_outcomes(passed=3) +def test_multiple_browsers_with_overridden_page_fixture( + testdir: pytest.Testdir, +) -> None: + # Overriding the "page" fixture must not disable running the test against + # each requested browser. + # https://github.com/microsoft/playwright-pytest/issues/172 + testdir.makepyfile( + """ + import pytest + + @pytest.fixture + def page(page): + yield page + + def test_a(page): + pass + """ + ) + result = testdir.runpytest( + "--collect-only", "-q", "--browser", "chromium", "--browser", "firefox" + ) + assert result.ret == 0 + result.stdout.fnmatch_lines(["*test_a*chromium*", "*test_a*firefox*"]) + + def test_browser_context_args(testdir: pytest.Testdir) -> None: testdir.makeconftest( """