Assertions v0.5.0 Assertions View Source

Helpful functions to help you write better tests.

Link to this section Summary

Functions

Tests if two lists have the same elements without asserting they are in the same order

Tests if two lists have the same elements according to a given comparison function without asserting they are in the same order

Tests if two maps have the same values at the given keys

Tests that messages matching the given patterns, and only those messages, are received in order within the given time period, specified in milliseconds

Tests that a message matching the given pattern, and only that message, is received within the given time period, specified in milliseconds

Tests if two structs have the same values at the given keys

Link to this section Functions

Link to this function lists_equal?(left, right) View Source

Tests if two lists have the same elements without asserting they are in the same order.

When you compare two lists for equality using ==, order matters, which means assert [1,2,3] == [1,3,2] fails. However, for many situations, the order of elements in a list doesn’t matter.

If you only care that two lists have exactly the same elements, but not what order those elements are in, this is the assertion for you!

Examples

iex> lists_equal?([1,2,3], [1,3,2])
true

iex> lists_equal?([1,2,4], [1,3,2])
false

iex> lists_equal?([1,2,3,4], [1,3,2])
false

iex> lists_equal?([1,2,3], [1,3,2,4])
false
Link to this function lists_equal?(left, right, comparison) View Source

Tests if two lists have the same elements according to a given comparison function without asserting they are in the same order.

This is very similar to lists_equal?/2, but it allows you to determine how two elements in your list are considered equal. This is especially helpful when comparing lists of structs, since comparing structs for equality with == is very error prone.

The comparison function you pass as the third argument must be a function that takes two elements (one from the left list and one from the right list) and returns a boolean if those two elements are equal.

Examples

iex> lists_equal?([1,2,3], [1,3,2], &Kernel.==/2)
true

iex> lists_equal?(["12", "23.5"], ["23", "12 "], fn left, right ->
...>   {left_int, _} = Integer.parse(left)
...>   {right_int, _} = Integer.parse(right)
...>   left_int == right_int
...> end)
true

iex> left = [DateTime.utc_now(), Date.utc_today()]
iex> right = [Date.utc_today(), DateTime.utc_now()]
iex> lists_equal?(left, right, &structs_equal?(&1, &2, [:year, :month, :day]))
true

iex> left = [DateTime.utc_now()]
iex> right = [Date.utc_today(), DateTime.utc_now()]
iex> lists_equal?(left, right, &structs_equal?(&1, &2, [:year, :month, :day]))
false

iex> left = [Date.utc_today(), DateTime.utc_now()]
iex> right = [DateTime.utc_now()]
iex> lists_equal?(left, right, &structs_equal?(&1, &2, [:year, :month, :day]))
false
Link to this function map_values_equal?(left, right, keys, options \\ [strict: true]) View Source

Tests if two maps have the same values at the given keys.

Examples

iex> left = %{first: :first, second: :second}
iex> right = %{first: :first, second: :second, third: :third}
iex> map_values_equal?(left, right, [:first, :second])
true

iex> left = %{first: "first", second: :second}
iex> right = %{first: :first, second: :second, third: :third}
iex> map_values_equal?(left, right, [:first, :second])
false

iex> left = %{first: :first, second: :second}
iex> right = %{first: :first, third: :third}
iex> map_values_equal?(left, right, [:first, :second])
false

By default if both maps are missing a given key, they are not considered equal.

iex> left = %{first: :first, second: :second}
iex> right = %{first: :first, second: :second, third: :third}
iex> map_values_equal?(left, right, [:first, :second, "not_there"])
false

If you would like maps to be considered equal in this case, you can pass strict: false as the fourth argument.

iex> left = %{first: :first, second: :second}
iex> right = %{first: :first, second: :second, third: :third}
iex> map_values_equal?(left, right, [:first, :second, "not_there"], strict: false)
true
Link to this macro receive_exactly?(expected_patterns, timeout \\ 100) View Source (macro)

Tests that messages matching the given patterns, and only those messages, are received in order within the given time period, specified in milliseconds.

This is an expansion of receive_only?/2. See the documentation there for details on the behavior of this function.

Examples

iex> send(self(), :hello)
iex> send(self(), :hello_again)
iex> send(self(), :goodbye)
iex> receive_exactly?([:hello, :hello_again, :goodbye])
true

iex> send(self(), :hello)
iex> Process.send_after(self(), :hello_again, 50)
iex> receive_exactly?([:hello, :hello_again])
true

iex> send(self(), :hello_again)
iex> send(self(), :hello)
iex> receive_exactly?([:hello, :hello_again])
false

iex> send(self(), :hello)
iex> send(self(), :goodbye)
iex> send(self(), :hello_again)
iex> receive_exactly?([:hello, :hello_again])
false

iex> send(self(), :hello)
iex> send(self(), :hello_again)
iex> send(self(), :goodbye)
iex> receive_exactly?([:hello, :hello_again])
false

iex> send(self(), :goodbye)
iex> send(self(), :hello)
iex> send(self(), :hello_again)
iex> receive_exactly?([:hello, :hello_again])
false

iex> hello = :hello
iex> send(self(), hello)
iex> send(self(), :hello_again)
iex> receive_exactly?([^hello, :hello_again])
true

iex> hello = :hello
iex> send(self(), :hello_again)
iex> send(self(), hello)
iex> receive_exactly?([^hello, _])
false
Link to this macro receive_only?(expected_pattern, timeout \\ 100) View Source (macro)

Tests that a message matching the given pattern, and only that message, is received within the given time period, specified in milliseconds.

The optional second argument is a timeout for the receive to wait for the expected message, and defaults to 100ms.

If you want to check that no message was received before the expected message, and that no message is received for a given time after calling receive_only?/2, you can combine received_only?/2 with ExUnit.Assertions.refute_receive/3.

assert receive_only?(:hello)
refute_receive _, 100

Examples

iex> send(self(), :hello)
iex> receive_only?(:hello)
true

iex> send(self(), [:hello])
iex> receive_only?([_])
true

iex> a = :hello
iex> send(self(), :hello)
iex> receive_only?(^a)
true

iex> send(self(), :hello)
iex> send(self(), :hello_again)
iex> receive_only?(:hello)
false

If a message is received after the function has matched a message to the given pattern, but the second message is received before the timeout, that second message is ignored and the function returns true.

This function only tests that the message that matches the given pattern was the first message in the process inbox, and that nothing was sent between the sending the message that matches the pattern and when receive_only?/2 was called.

iex> Process.send_after(self(), :hello, 20)
iex> Process.send_after(self(), :hello_again, 50)
iex> receive_only?(:hello, 100)
true

iex> Process.send_after(self(), :hello, 50)
iex> Process.send_after(self(), :hello_again, 20)
iex> receive_only?(:hello, 100)
false
Link to this function structs_equal?(left, right, keys) View Source

Tests if two structs have the same values at the given keys.

Directly comparing structs for equality using == can be very tricky, which is why you almost never want to do that. Using this assertion, you get to determine what makes two structs equal while allowing for inconsequential differences.

Examples

iex> left = DateTime.utc_now()
iex> right = Date.utc_today()
iex> structs_equal?(left, right, [:year, :month, :day])
true

iex> left = DateTime.utc_now()
iex> right = Date.utc_today()
iex> structs_equal?(left, right, [:year, :month, :day, :second])
false