Skip to content

Conversation

roberfi
Copy link
Contributor

@roberfi roberfi commented Jul 3, 2025

Fixes #195.

Using "browser_name" as an indirect parameter, pytest keeps the original order of the tests.

Without pytest-playwright:

my_tests/test_a.py::test_aa[case_1] PASSED                                                 [ 12%]
my_tests/test_a.py::test_aa[case_2] PASSED                                                 [ 25%]
my_tests/test_a.py::test_ab[case_1] PASSED                                                 [ 37%]
my_tests/test_a.py::test_ab[case_2] PASSED                                                 [ 50%]
my_tests/test_b.py::test_ba[case_1] PASSED                                                 [ 62%]
my_tests/test_b.py::test_ba[case_2] PASSED                                                 [ 75%]
my_tests/test_b.py::test_bb[case_1] PASSED                                                 [ 87%]
my_tests/test_b.py::test_bb[case_2] PASSED                                                 [100%]

With pytest-playwright before the fix:

my_tests/test_a.py::test_aa[chromium-case_1] PASSED                                        [  4%]
my_tests/test_a.py::test_ab[chromium-case_1] PASSED                                        [  8%]
my_tests/test_b.py::test_ba[chromium-case_1] PASSED                                        [ 12%]
my_tests/test_b.py::test_bb[chromium-case_1] PASSED                                        [ 16%]
my_tests/test_a.py::test_aa[chromium-case_2] PASSED                                        [ 20%]
my_tests/test_a.py::test_ab[chromium-case_2] PASSED                                        [ 25%]
my_tests/test_b.py::test_ba[chromium-case_2] PASSED                                        [ 29%]
my_tests/test_b.py::test_bb[chromium-case_2] PASSED                                        [ 33%]
my_tests/test_a.py::test_aa[firefox-case_1] PASSED                                         [ 37%]
my_tests/test_a.py::test_ab[firefox-case_1] PASSED                                         [ 41%]
my_tests/test_b.py::test_ba[firefox-case_1] PASSED                                         [ 45%]
my_tests/test_b.py::test_bb[firefox-case_1] PASSED                                         [ 50%]
my_tests/test_a.py::test_aa[firefox-case_2] PASSED                                         [ 54%]
my_tests/test_a.py::test_ab[firefox-case_2] PASSED                                         [ 58%]
my_tests/test_b.py::test_ba[firefox-case_2] PASSED                                         [ 62%]
my_tests/test_b.py::test_bb[firefox-case_2] PASSED                                         [ 66%]
my_tests/test_a.py::test_aa[webkit-case_1] PASSED                                          [ 70%]
my_tests/test_a.py::test_ab[webkit-case_1] PASSED                                          [ 75%]
my_tests/test_b.py::test_ba[webkit-case_1] PASSED                                          [ 79%]
my_tests/test_b.py::test_bb[webkit-case_1] PASSED                                          [ 83%]
my_tests/test_a.py::test_aa[webkit-case_2] PASSED                                          [ 87%]
my_tests/test_a.py::test_ab[webkit-case_2] PASSED                                          [ 91%]
my_tests/test_b.py::test_ba[webkit-case_2] PASSED                                          [ 95%]
my_tests/test_b.py::test_bb[webkit-case_2] PASSED                                          [100%]

With pytest-playwright after the fix:

my_tests/test_a.py::test_aa[chromium-case_1] PASSED                                        [  4%]
my_tests/test_a.py::test_aa[chromium-case_2] PASSED                                        [  8%]
my_tests/test_a.py::test_ab[chromium-case_1] PASSED                                        [ 12%]
my_tests/test_a.py::test_ab[chromium-case_2] PASSED                                        [ 16%]
my_tests/test_b.py::test_ba[chromium-case_1] PASSED                                        [ 20%]
my_tests/test_b.py::test_ba[chromium-case_2] PASSED                                        [ 25%]
my_tests/test_b.py::test_bb[chromium-case_1] PASSED                                        [ 29%]
my_tests/test_b.py::test_bb[chromium-case_2] PASSED                                        [ 33%]
my_tests/test_a.py::test_aa[firefox-case_1] PASSED                                         [ 37%]
my_tests/test_a.py::test_aa[firefox-case_2] PASSED                                         [ 41%]
my_tests/test_a.py::test_ab[firefox-case_1] PASSED                                         [ 45%]
my_tests/test_a.py::test_ab[firefox-case_2] PASSED                                         [ 50%]
my_tests/test_b.py::test_ba[firefox-case_1] PASSED                                         [ 54%]
my_tests/test_b.py::test_ba[firefox-case_2] PASSED                                         [ 58%]
my_tests/test_b.py::test_bb[firefox-case_1] PASSED                                         [ 62%]
my_tests/test_b.py::test_bb[firefox-case_2] PASSED                                         [ 66%]
my_tests/test_a.py::test_aa[webkit-case_1] PASSED                                          [ 70%]
my_tests/test_a.py::test_aa[webkit-case_2] PASSED                                          [ 75%]
my_tests/test_a.py::test_ab[webkit-case_1] PASSED                                          [ 79%]
my_tests/test_a.py::test_ab[webkit-case_2] PASSED                                          [ 83%]
my_tests/test_b.py::test_ba[webkit-case_1] PASSED                                          [ 87%]
my_tests/test_b.py::test_ba[webkit-case_2] PASSED                                          [ 91%]
my_tests/test_b.py::test_bb[webkit-case_1] PASSED                                          [ 95%]
my_tests/test_b.py::test_bb[webkit-case_2] PASSED                                          [100%]

@roberfi roberfi marked this pull request as draft July 3, 2025 17:43
@roberfi
Copy link
Contributor Author

roberfi commented Jul 3, 2025

@roberfi roberfi force-pushed the fix-tests-ordering branch from 9b912a3 to 4ac040c Compare July 7, 2025 16:41
@roberfi roberfi marked this pull request as ready for review July 7, 2025 17:46
Comment on lines 92 to +95
def pytest_generate_tests(metafunc: Any) -> None:
if "browser_name" in metafunc.fixturenames:
browsers = metafunc.config.option.browser or ["chromium"]
metafunc.parametrize("browser_name", browsers, scope="session")
metafunc.parametrize("browser_name", browsers, scope="session", indirect=True)
Copy link

@MosZhao MosZhao Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If check the browser_name in metafuc.params the browser_name can support get browser from marker.parametrize of testcase. Such as the code:

Suggested change
def pytest_generate_tests(metafunc: Any) -> None:
if "browser_name" in metafunc.fixturenames:
browsers = metafunc.config.option.browser or ["chromium"]
metafunc.parametrize("browser_name", browsers, scope="session")
metafunc.parametrize("browser_name", browsers, scope="session", indirect=True)
def pytest_generate_tests(metafunc: Any) -> None:
if "browser_name" in metafunc.fixturenames:
browsers = metafunc.config.option.browser or ["chromium"]
if hasattr(metafunc, "params") and "browser_name" not in metafunc.params:
metafunc.parametrize("browser_name", browsers, scope="session")

And the fixture browser_name changes is not required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that, in this case, it should better be:

if "browser_name" not in getattr(metafunc, "params", {}):
    metafunc.parametrize("browser_name", browsers, scope="session")

Because, I've seen that "params" could not be present if not parameters have been defined yet and "brower_name" parametrization is not added then.

But, apart from that, how does this fix the problem? Tests are still wrongly sorted with this change:

pytest --browser chromium --browser firefox 

tests/gui_e2e/my_tests/test_a.py::test_aa[chromium-case_1] PASSED                                        [  6%]
tests/gui_e2e/my_tests/test_a.py::test_ab[chromium-case_1] PASSED                                        [ 12%]
tests/gui_e2e/my_tests/test_b.py::test_ba[chromium-case_1] PASSED                                        [ 18%]
tests/gui_e2e/my_tests/test_b.py::test_bb[chromium-case_1] PASSED                                        [ 25%]
tests/gui_e2e/my_tests/test_a.py::test_aa[chromium-case_2] PASSED                                        [ 31%]
tests/gui_e2e/my_tests/test_a.py::test_ab[chromium-case_2] PASSED                                        [ 37%]
tests/gui_e2e/my_tests/test_b.py::test_ba[chromium-case_2] PASSED                                        [ 43%]
tests/gui_e2e/my_tests/test_b.py::test_bb[chromium-case_2] PASSED                                        [ 50%]
tests/gui_e2e/my_tests/test_a.py::test_aa[firefox-case_1] PASSED                                         [ 56%]
tests/gui_e2e/my_tests/test_a.py::test_ab[firefox-case_1] PASSED                                         [ 62%]
tests/gui_e2e/my_tests/test_b.py::test_ba[firefox-case_1] PASSED                                         [ 68%]
tests/gui_e2e/my_tests/test_b.py::test_bb[firefox-case_1] PASSED                                         [ 75%]
tests/gui_e2e/my_tests/test_a.py::test_aa[firefox-case_2] PASSED                                         [ 81%]
tests/gui_e2e/my_tests/test_a.py::test_ab[firefox-case_2] PASSED                                         [ 87%]
tests/gui_e2e/my_tests/test_b.py::test_ba[firefox-case_2] PASSED                                         [ 93%]
tests/gui_e2e/my_tests/test_b.py::test_bb[firefox-case_2] PASSED                                         [100%]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion does not keep the indirect=Ture.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, but then it does not fix the sorting problem

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about impl, trylast=true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean using this?

@pytest.hookimpl(trylast=True)
def pytest_generate_tests(metafunc: Any) -> None:
    if "browser_name" in metafunc.fixturenames:
        browsers = metafunc.config.option.browser or ["chromium"]
        metafunc.parametrize("browser_name", browsers, scope="session")

The order is even worse:

pytest --browser chromium --browser firefox 

my_tests/test_a.py::test_aa[case_1-chromium] PASSED                                        [  6%]
my_tests/test_a.py::test_ab[case_1-chromium] PASSED                                        [ 12%]
my_tests/test_b.py::test_ba[case_1-chromium] PASSED                                        [ 18%]
my_tests/test_b.py::test_bb[case_1-chromium] PASSED                                        [ 25%]
my_tests/test_a.py::test_aa[case_1-firefox] PASSED                                         [ 31%]
my_tests/test_a.py::test_ab[case_1-firefox] PASSED                                         [ 37%]
my_tests/test_b.py::test_ba[case_1-firefox] PASSED                                         [ 43%]
my_tests/test_b.py::test_bb[case_1-firefox] PASSED                                         [ 50%]
my_tests/test_a.py::test_aa[case_2-chromium] PASSED                                        [ 56%]
my_tests/test_a.py::test_ab[case_2-chromium] PASSED                                        [ 62%]
my_tests/test_b.py::test_ba[case_2-chromium] PASSED                                        [ 68%]
my_tests/test_b.py::test_bb[case_2-chromium] PASSED                                        [ 75%]
my_tests/test_a.py::test_aa[case_2-firefox] PASSED                                         [ 81%]
my_tests/test_a.py::test_ab[case_2-firefox] PASSED                                         [ 87%]
my_tests/test_b.py::test_ba[case_2-firefox] PASSED                                         [ 93%]
my_tests/test_b.py::test_bb[case_2-firefox] PASSED                                         [100%]

Copy link

@MosZhao MosZhao Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you apply the changes about browser_name first? We need set browser_name list for part cases not all.

if "browser_name" not in getattr(metafunc, "params", {}):
    metafunc.parametrize("browser_name", browsers, scope="session")

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean this?

@pytest.hookimpl(trylast=True)
def pytest_generate_tests(metafunc: Any) -> None:
    if "browser_name" in metafunc.fixturenames and "browser_name" not in getattr(metafunc, "params", {}):
        browsers = metafunc.config.option.browser or ["chromium"]
        metafunc.parametrize("browser_name", browsers, scope="session")

It is the same than in the previous case:

pytest --browser chromium --browser firefox 

my_tests/test_a.py::test_aa[case_1-chromium] PASSED                                        [  6%]
my_tests/test_a.py::test_ab[case_1-chromium] PASSED                                        [ 12%]
my_tests/test_b.py::test_ba[case_1-chromium] PASSED                                        [ 18%]
my_tests/test_b.py::test_bb[case_1-chromium] PASSED                                        [ 25%]
my_tests/test_a.py::test_aa[case_1-firefox] PASSED                                         [ 31%]
my_tests/test_a.py::test_ab[case_1-firefox] PASSED                                         [ 37%]
my_tests/test_b.py::test_ba[case_1-firefox] PASSED                                         [ 43%]
my_tests/test_b.py::test_bb[case_1-firefox] PASSED                                         [ 50%]
my_tests/test_a.py::test_aa[case_2-chromium] PASSED                                        [ 56%]
my_tests/test_a.py::test_ab[case_2-chromium] PASSED                                        [ 62%]
my_tests/test_b.py::test_ba[case_2-chromium] PASSED                                        [ 68%]
my_tests/test_b.py::test_bb[case_2-chromium] PASSED                                        [ 75%]
my_tests/test_a.py::test_aa[case_2-firefox] PASSED                                         [ 81%]
my_tests/test_a.py::test_ab[case_2-firefox] PASSED                                         [ 87%]
my_tests/test_b.py::test_ba[case_2-firefox] PASSED                                         [ 93%]
my_tests/test_b.py::test_bb[case_2-firefox] PASSED                                         [100%]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pytest-playwright--parameterization, cases order Not what I expected
2 participants