WaitForIt.Test (WaitForIt v2.2.0)

Copy Markdown View Source

Assertions for waiting on asynchronous and concurrent activity in ExUnit tests.

These macros build on the WaitForIt waiting machinery but, instead of returning a falsy value or raising a WaitForIt.TimeoutError on timeout, they fail the test with a regular ExUnit.AssertionError — so failures read like any other ExUnit failure, complete with the source expression and the last value that was seen before giving up.

Usage

Bring the assertions into your test module with either import or use:

defmodule MyApp.SomeTest do
  use ExUnit.Case
  use WaitForIt.Test
end

Available assertions

All of them accept the same options as the other WaitForIt macros (:timeout, :interval, :pre_wait, :signal); see the WaitForIt module documentation. The defaults are tuned for tests and differ per assertion (noted on each).

Summary

Functions

Convenience: use WaitForIt.Test is equivalent to import WaitForIt.Test.

Asserts that the given expression stays truthy for the entire wait window.

Asserts that the given expression eventually succeeds, waiting and re-evaluating until it does or the timeout elapses.

Asserts that the given expression never becomes truthy within the wait window.

Functions

__using__(opts)

(macro)

Convenience: use WaitForIt.Test is equivalent to import WaitForIt.Test.

assert_always(expression, opts \\ [])

(macro)

Asserts that the given expression stays truthy for the entire wait window.

Re-evaluates the expression until it becomes falsy (a failure) or the timeout elapses (a success). Because waiting is poll-based, a brief falsy blip between evaluations may be missed; tune :interval to sample as often as you need.

Defaults to timeout: 100 and interval: 10.

Examples

assert_always circuit_closed?(), timeout: 500

assert_eventually(expression, opts \\ [])

(macro)

Asserts that the given expression eventually succeeds, waiting and re-evaluating until it does or the timeout elapses.

Two forms are supported:

  • a plain expression, which must eventually evaluate to a truthy value, and
  • a match expression of the form pattern = expression, which waits until the right-hand side matches pattern and then binds the pattern's variables into the surrounding scope, exactly like assert pattern = expression.

Returns the value that ended the wait. On timeout, fails with an ExUnit.AssertionError that includes the source expression and the last value that was evaluated.

Defaults to timeout: 1_000 and interval: 10.

Examples

# Truthy form:
assert_eventually Repo.get(User, id).confirmed

# Match form (binds `user` for later use):
assert_eventually {:ok, user} = fetch_user(id), timeout: 2_000
assert user.name == "Elijah"

refute_eventually(expression, opts \\ [])

(macro)

Asserts that the given expression never becomes truthy within the wait window.

Re-evaluates the expression until it becomes truthy (a failure) or the timeout elapses (a success). Because confirming the negative requires waiting out the whole window, this assertion always waits up to its timeout when it passes; keep the timeout short.

Defaults to timeout: 100 and interval: 10.

Examples

refute_eventually error_reported?()