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
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
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
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
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
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
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