-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
(This is a high-level issue that proposes making pytest more thread safe; I'm definitely looking for feedback, discussion, and confirmation this is a good direction here.)
Background
This issue comes out of a brief conversation on the pytest discord:
[@ngoldbaum] out of curiosity, if there were funding for work on improving pytest’s thread safety, is that something that the project might be interested in? For the work we’ve been doing so far we’ve contracted David Woods to work on Cython, David Hewitt to work on PyO3, and Liam DeVoe to work on Hypothesis. Is there an opportunity for pytest as well?
[@The-Compiler] Personally I'm not too interested in it being thread-safe, but I'd absolutely support using our Opencollective funds to make it happen
[@RonnyPfannschmidt] my sentinent is the same - but i also want to note that i'd prefer thread safety in a manner that uses queues and non-shared state for fixtures & co (aka xdist-alike, just without separate node objects) - the key contention would be log/stdio capture state + managing pytest stores on nodes in a controlled manner
I don't presume to know the best direction for thread-safety in pytest, so I'm opening this issue to get some feedback on my understanding.
While this may be obvious to all involved, I want to at least give a brief motivation for thread-safety here. Python is working towards removing the global interpreter lock, in a python build version called free-threading. As free-threading progresses, it seems likely that more people will want to run multiple tests simultaneously in separate threads. In particular, it would be nice for free-threading development if pytest-xdist supported threading (in place of multiprocessing) as its worker primitive, so existing test suites can be run with pytest-xdist in threading mode to flush out concurrency bugs.
Proposal
I would summarize all of pytest as two (very complex) steps:
- Test collection.
- Test execution.
with some calls to pluggy thrown in during both.
From talking with @Zac-HD, I understand there's some appetite for parallelizing collection in pytest itself using threads, perhaps as a consequence of folding pytest-xdist into pytest. This would require making (1) test collection thread safe. I think that parallelized test collection is "merely" a performance improvement, so I'm not proposing it in this issue, though it may be something to keep in mind.
Instead I want to focus on (2); making test execution thread-safe. Here is my understanding of the required work there:
- Make pluggy thread-safe, as hooks will be called from multiple threads.
- It's possible this work is either minimal or zero, if pluggy is already thread safe.
- Guarantee all (feasible) built-in fixtures are thread-safe.
- I don't (yet) know pytest internals enough to judge how difficult this will be.
- Some fixtures, like
monkeypatch
andcapsys
, don't seem possible to make thread-safe. Perhaps someone knows an arcanely cursed way to achieve this?
- Make pytest data collection during tests thread-safe.
- the tracking of the number of xfails, successes, failures, etc.
- Document the thread-safety guarantees, including what is and is not safe.
- Add an opt-in execution model to pytest-xdist which uses threads instead of processes.
- If we're done our job right up to this point, this should be conceptually simple, though it may require some involved changes to pytest-xdist to support this.
And finally;
- Test the heck out of this.
- I put a substantial amount of effort into testing thread-safety when migrating Hypothesis: Add threading CI job HypothesisWorks/hypothesis#4489. I would expect to do so again here, though I don't yet know the best way to do so.
Open questions
- If we do leave fixtures like
monkeypatch
thread-unsafe, how should this interact with pytest-xdist's proposed threading mode? A few options: do nothing; print a warning; error; or skip the test. I don't like half of these!
cc: @ngoldbaum, @lysnikolaou