You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 11, 2025. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 11, 2025. It is now read-only.
Currently, when using subtest, one has to propagate the subtest object in each of the submethods, adding boilerplate:
deftest_xyz(subtests):
assert_fn(x, y, subtests) # Propagate subtest to all sub functionsdefassert_fn(x, y, subtests):
withsubtests.test('a'):
withsubtests.test('x'):
assert_child_fn(x, subtests) # Additional function with subtestswithsubtests.test('y'):
assert_child_fn(x, subtests)
It would be nice if there was instead a global subtest function which could be called directly. The above code could be rewritten as
@pytest.mark.usefixture('subtest')deftest_xyz():
assert_fn(x, y) # No more subtest argumentdefassert_fn(x, y):
withpytest.subtest('a'):
withpytest.subtest('x'):
assert_child_fn(x)
withpytest.subtest('y'):
assert_child_fn(x)
Of course, calling pytest.subtests would raise an error if executed in a test which does not use the subtest fixture.
But this would make it easier to make modular tests function.
If pytest.subtest is not possible, import subtests directly would be great too.
Contrary to pytest.warns or pytest.raises, subtest support needs to capture exceptions, suppress them, and store that somewhere. Making it a global function would mean to store those captured exceptions in global variable, which I'm not a big fan of. Internally we also need to invoke hooks to generate reports, and we can't access those globally.
So while I agree it would be nice, I'm not sure it is possible to implement it without some ugly hacks.
I'm leaving this open anyway to review this in the future. 👍
In case someone else is interested, I've implemented a small wrapper around subtests which add #45 and #44 (this issue):
frometilsimportepywith_subtests=epy.testing.with_subtests# Needed to register the fixture for this file@pytest.mark.usefixtures('with_subtests')deftest_dtype():
withepy.testing.subtests.test("a"): # Do not need to propagate a subtests object in sub-functionswithepy.testing.subtests.test("b"): # Nested subtest is reported as `a/b`assert1==2
Test reported as ___________ test_abc [a/b] ___________
Activity
nicoddemus commentedon Jun 25, 2021
Hi @Conchylicultor,
Thanks for the suggestion!
Contrary to
pytest.warnsorpytest.raises, subtest support needs to capture exceptions, suppress them, and store that somewhere. Making it a global function would mean to store those captured exceptions in global variable, which I'm not a big fan of. Internally we also need to invoke hooks to generate reports, and we can't access those globally.So while I agree it would be nice, I'm not sure it is possible to implement it without some ugly hacks.
I'm leaving this open anyway to review this in the future. 👍
RonnyPfannschmidt commentedon Jun 25, 2021
@nicoddemus once we can provide contextvars it may be easier, but we should ensure its not quickly turned into a easy abused global
im currently leaning towards not enabling it
Conchylicultor commentedon Sep 8, 2022
In case someone else is interested, I've implemented a small wrapper around subtests which add #45 and #44 (this issue):
Test reported as
___________ test_abc [a/b] ___________As part of https://github.com/google/etils
bluetech commentedon Oct 20, 2025
I'm with @RonnyPfannschmidt, pytest avoids contextvars and such and I don't think we should start.