Basics
This check is disabled by default.
Learn how to enable it via .credo.exs.
This check has a base priority of high and works with any version of Elixir.
Explanation
A test that waits for something asynchronous polls the condition with the suite's
eventually/2 helper (test/support/eventually.ex), never a sleep.
elixir-code-review, references/test-quality.md:
Wait with
eventually/2, never a hand-rolled loop. A test that waits for an asynchronous condition callseventually/2(oreventually_render/3against a LiveView): one documented budget, and it always flunks when time runs out.
A bare Process.sleep(n) in a test is one of two things, and both are findings:
- a guess — "the cast has surely landed by now". It is flaky under load and slow when
idle, and the fix is to wait on the condition itself with
eventually/2. - a polling loop — the sleep inside a hand-written retry. Every such loop picks its
own budget, and some return
falseor:okon timeout and rely on every caller toassert, so a test whose condition never came true can pass. Each new test copies whichever loop sits nearest.
Scope the check to test/ and exclude test/support/ in .credo.exs: that is where the one
sanctioned loop lives. Process.sleep(:infinity) is out of scope too — it parks a process
(a holder that must stay alive until the test kills it) and guesses at no timing.
What remains is a sleep that is the subject: an absence held for a window ("the supervisor must not restart it"), a TTL that must lapse on the wall clock, a gap staged between two events with no signal to wait on. Those carry an inline waiver that says so.
Check-Specific Parameters
There are no specific parameters for this check.
General Parameters
Like with all checks, general params can be applied.
Parameters can be configured via the .credo.exs config file.