Solvedkotlinx.coroutines Support runBlocking for UI Tests
βοΈAccepted Answer
It is already reverted in develop
branch. Will be part of the next build (tentatively 0.24.1
).
Other Answers:
Such features are usually implemented as default safety mechanism against accidental misusages, but when they start to make programming experience worse or require explicit opt-in (especially on every call-site) it's a good marker that feature is harmful.
I think we should revert this change:
- There are cases when blocking in UI is legit
- UI check is not well integrated with test frameworks
- The workaround with system property for tests is unstable and may lead to production crashes (where this property is not set) and this is the opposite of what we wanted
- Flag
failsInUI
is a debatable boilerplate-like solution. E.g. when somewhen have to write blocking test he may just pass this flag everywhere (becauserunTest
is not well-discoverable or entry point may be hidden in production code) - Enabling this feature only in developer mode is not that useful as it's opt-in feature (which should be discovered first) and carries much less value
It is possible to create a test dependency for coroutine to put there runTest
and whatever is needed.
As a personal consideration runBlocking
should check the thread only in development mode.
In production mode :
- the check is superfluous
- the code have to run as much as possible
As mentionned by @gildor (in #458) and @svenjacobs (in #227), there are other uses-cases for which it is valid to block the UI thread when it comes to application initialization and cleanup. Especially when theses operations are fast, it would add unnecessary complexity to do it in a non-blocking fashion.
The more it goes, the more I am getting convinced think that:
- developers should be able to block any thread whenever they decide it makes sense. (even if it is bad practice to do so)
- the fail-fast feature of
runBlocking
should only fail in debug mode (as proposed by @fvasco)
As mentionned by @PaulWoitaschek in #458, there is a problem with the fact that
runBlocking
fails by default in a UI thread (see #227).The problem is that if one wants to perform UI tests, then (depending on tool used) the test methods may be called on the UI thread. (this is apparently the case for android, and it is the case for TestFx with Junit5)
Then there is actually no good solution for theses tests. Yes, one could run the tests using the system property introduced in #458, and the tests will pass. But this is not a good solution, because the tests will pass even if there is a
runBlocking
in the actual production code, and we'd end-up with passing tests, but failing application.So here is two proposed solutions:
runTest
method which would not fail, even if in UI thread (proposed by @PaulWoitaschek).failsInUI
(or better named) argument torunBlocking
which would allow to explicitly by-pass the checkers (only for this call of runBlocking)