Tack.Credo.Check.SleepInTest (pica v0.1.0)

Copy Markdown View Source

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 calls eventually/2 (or eventually_render/3 against 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 false or :ok on timeout and rely on every caller to assert, 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.