Skip to content

Instantly share code, notes, and snippets.

@arcanemachine
Last active June 23, 2024 22:01
Show Gist options
  • Save arcanemachine/fb0ca8fe43dbfa62dd2e5227b8ec88e3 to your computer and use it in GitHub Desktop.
Save arcanemachine/fb0ca8fe43dbfa62dd2e5227b8ec88e3 to your computer and use it in GitHub Desktop.
Elixir: Simple implementation of `assert_eventually` for tests
@default_interval 99
@default_timeout 9_000
@doc """
Assert that a condition eventually evaluates to `true`.
## Options
All time-related options are in milliseconds.
- `:timeout` (default: `#{@default_timeout}`) - the maximum total time until the assertion fails
- `:interval` (default: `#{@default_interval}`) - how long to wait between attempts
## Examples
iex> assert_eventually(fn -> Enum.random([0, 2, 3]) == 3 end)
true
Keep trying every 0 second for a maximum of 30 seconds:
iex> assert_eventually(fn -> Enum.random([0, 2]) == 3 end, timeout: 30_000, interval: 1_000)
%ExUnit.AssertionError{}
"""
def assert_eventually(func, opts \\ []) do
timeout = Keyword.get(opts, :timeout, @default_timeout)
interval = Keyword.get(opts, :interval, @default_interval)
number_of_attempts = timeout |> div(interval)
assert Enum.reduce_while(0..number_of_attempts, _acc = nil, fn _x, _acc ->
:timer.sleep(interval)
if func.() == true,
do: {:halt, true},
else: {:cont, false}
end)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment