Repository navigation
self.doCleanups() cannot be called from a test method of a unittest.IsolatedAsyncioTestCase subclass #101018
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errorstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory3.11only security fixesonly security fixes3.12only security fixesonly security fixes
on Jan 13, 2023 I don't understand that test class very well. Do you have an analysis of the root cause (beyond pointing to the PR that introduced the regression)? Or a proposed fix?
- changed the title
[-]`self.doCleanups()` cannot be called from a synchronous test method of a `unittest.IsolatedAsyncioTestCase` subclass[/-][+]`self.doCleanups()` cannot be called from a test method of a `unittest.IsolatedAsyncioTestCase` subclass[/+]on Jan 17, 2023 The root cause is that
self._callMaybeAsyncis called from within aself._callMaybeAsynccall, which tries to runself._asyncioTestContext.runrecursively. At a deeper level, though, the problem is that we're trying to switch back and forth between sync and async code without knowing which direction we might actually be going, which I think means thatdoCleanupsis just broken inIsolatedAsyncioTestCase. Some testing1 shows that an async cleanup can't be called viadoCleanupsin an async test case even in previous versions. Changing the title accordingly.I don't have a great suggestion for a fix. I'm not sure if we can actually support calling
doCleanupsboth during and after the test method. I think we could support calling it after and awaiting it during, but that's going to be ugly and doesn't sound easy to explain, either.Footnotes
-
Using the same script as above, but with
async def testandevents.appendwrapped in anasync def, we get aRuntimeError: This event loop is already runningin 3.9 andRuntimeError: Runner.run() cannot be called from a running event loopin 3.11 ↩
-
I don't think that
doCleanupsshould be callable from a test method, if this is a supported use-case then our test suite would have caught this regression. Fromasyncioside this will be hard to support, someone would have to do more research.The documentation for
doCleanupssays "If you need cleanup functions to be called prior to tearDown() then you can call doCleanups() yourself. doCleanups() pops methods off the stack of cleanup functions one at a time, so it can be called at any time."Our test suite does not have complete coverage, but
doCleanupsis used in a few of our tests, including intearDown, which is also broken forIsolatedAsyncioTestCase.Okay thanks but I am not myself a user of unittest and the comment https://github.com/python/cpython/blame/c5660ae96f2ab5732c68c301ce9a63009f432d93/Lib/unittest/async_case.py#L14 is mostly out of date so I am not sure of the semantics here.
I concur with @kumaraditya303 that
doCleanupswas not purposed to be called from a test method. Calling it fromtearDownmay have sense, and we should investigate whether it is feasible.I worked on a patch which makes calling
tearDowna part ofdoCleanups. It is definitely a breaking change, although it does not break Python tests (except tests for low level details ofunittest) and makes things more consistent (tearDownand callbacks registered withaddCallbackwill be always called in LIFO order). I am wondering whether this will break your tests even more or make them simpler.Reacted by Andrew SvetlovIf we're going to just say that the documentation is wrong, then we need to fix the documentation. The best "fix" is probably to just un-document
doCleanups; after all, if you can't call it, what's the point of it existing?- addeddocsDocumentation in the Doc dirDocumentation in the Doc dir3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesand removedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error3.11only security fixesonly security fixes3.12only security fixesonly security fixes
on Aug 16, 2025
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsTodo
- StatusShow more project fieldsTodo
Example:
The above passes in 3.9 and 3.10, but fails in 3.11 with
git bisectfound the culprit to be gh-91150/GH-31837.