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
I'm thinking of creating a small helper class that only handles cleanup methods — addCleanup, enterContext, and doCleanups — without inheriting from TestCase. That way, it avoids exposing any extra functionality like assert* methods and keeps things more contained. What are your thoughts on this?
@encukou What are your thoughts on the implementation for this issue?
I’m considering creating a separate helper class _SubTestCleanupHelper with functionality similar to TestCase, but without exposing unnecessary features like _subTest.
The downside is that it would introduce some duplicated code.
Leave the interface as is and expose _SubTest as an opaque object with a documented interface. Let's not care about the extra methods that are added, let's only care about documenting those that should be public.
Use a proxy object with an overridden __getattr__ that only returns a subset of allowed methods. The rest would raise RuntimeError if they are inherited from TestCase and not overloaded. We shouldn't expect _SubTest to be a public class so we shouldn't worry about users subclassing this class and deal with this in our custom __getattr__.
The first solution would at least make any (CPython) code that is currently using _SubTest internally easier to maintain.
But we need to add asynchronous variants to subTest in IsolatedAsyncIOTestCase. This means two implementations of subTest.
It's unique advantage is that you can add callbacks for the outer scope and break strict LILO order. But I don't know how large a demand for it. The implementation will be complicated.
addCleanup(), doCleanups(), etc will only work within a fence. All callbacks added in a fence will be called after leaving a fence. It may help to solve also other issues.
But we will be able to fully understand the advantages and disadvantages only when we try to implement all three options.
Activity
encukou commentedon May 16, 2025
(If anyone wants to take it, go ahead! Otherwise I'll get to this eventually.)
StanFromIreland commentedon May 16, 2025
I can get to this in the evening:-) It's suprising that this was not implemented before!
ArunRawat404 commentedon May 17, 2025
If it's alright with you guys, I'd love to take on this issue.
StanFromIreland commentedon May 17, 2025
My implementation is not idea since _SubTest is a subclass and would therefore also expose asserts. I'd be interested to see what you have planned.
ArunRawat404 commentedon May 17, 2025
I'm thinking of creating a small helper class that only handles cleanup methods —
addCleanup,enterContext, anddoCleanups— without inheriting fromTestCase. That way, it avoids exposing any extra functionality likeassert*methods and keeps things more contained. What are your thoughts on this?StanFromIreland commentedon May 17, 2025
I thought about that, but IMO it is pretty messy with a lot of duplicated code, so I don’t know. It is probably the only option.
ArunRawat404 commentedon May 17, 2025
Yes, it will be messy with duplicated code but I guess it's better than exposing unnecessary functionality. I also not able to think of any other way.
ArunRawat404 commentedon May 18, 2025
@encukou What are your thoughts on the implementation for this issue?
I’m considering creating a separate helper class
_SubTestCleanupHelperwith functionality similar to TestCase, but without exposing unnecessary features like_subTest.The downside is that it would introduce some duplicated code.
Would love to hear your thoughts or suggestions.
picnixz commentedon May 18, 2025
My 2c:
_SubTestas an opaque object with a documented interface. Let's not care about the extra methods that are added, let's only care about documenting those that should be public.__getattr__that only returns a subset of allowed methods. The rest would raise RuntimeError if they are inherited from TestCase and not overloaded. We shouldn't expect_SubTestto be a public class so we shouldn't worry about users subclassing this class and deal with this in our custom__getattr__.The first solution would at least make any (CPython) code that is currently using
_SubTestinternally easier to maintain.encukou commentedon May 19, 2025
I think it's best to leave
_SubTestfor reporting, and add a new object for the context.Don't worry about duplicated code until the solution is working and tested. Then it's time to deduplicate.
serhiy-storchaka commentedon Jun 4, 2025
Three ways to solve this issue was mentioned on the Discuss thread. With examples:
subTest.But we need to add asynchronous variants to
subTestinIsolatedAsyncIOTestCase. This means two implementations ofsubTest.It's unique advantage is that you can add callbacks for the outer scope and break strict LILO order. But I don't know how large a demand for it. The implementation will be complicated.
TestCase.It may be easier to implement for
IsolatedAsyncIOTestCase.addCleanup(),doCleanups(), etc will only work within a fence. All callbacks added in a fence will be called after leaving a fence. It may help to solve also other issues.But we will be able to fully understand the advantages and disadvantages only when we try to implement all three options.