View Source Moar.Assertions (Moar v1.62.0)
ExUnit assertions.
See also: siiibo/assert_match which is similar to this module's
assert_eq
function but with pattern matching.
Summary
Functions
Asserts that the left
list or map contains all of the items in the right
list or map,
or contains the single right
element if it's not a list or map. Returns left
or raises ExUnit.AssertionError
.
Asserts that the left
and right
values are equal. It returns the left
value unless the assertion fails,
or unless the :returning
option is used. As a special case, if the first argument is a string and the second
is a Regex, the comparison is done with the =~
operator instead of the ==
operator.
Asserts that datetime
is within recency
of now (in UTC), returning datetime
if the assertion succeeeds.
Asserts that a pre-condition and a post-condition are true after performing an action, returning the result of the action.
Refute that a condition is changed after performing an action, returning the result of the action.
Types
@type assert_eq_opt_shortcut() :: :downcase | :sort | :squish | :trim
@type assert_eq_opts() :: (any() -> any()) | {:apply, (any() -> any()) | assert_eq_opt_shortcut()} | assert_eq_opt_shortcut() | {:except, list()} | :ignore_order | {:ignore_order, boolean()} | {:ignore_whitespace, :leading_and_trailing} | {:map, (any() -> any()) | assert_eq_opt_shortcut()} | {:only, list()} | {:returning, any()} | {:whitespace, :squish | :trim} | {:within, number() | {number(), Moar.Duration.time_unit()}}
Functions
@spec assert_contains(map(), map()) :: map()
@spec assert_contains(list(), list() | any()) :: list()
Asserts that the left
list or map contains all of the items in the right
list or map,
or contains the single right
element if it's not a list or map. Returns left
or raises ExUnit.AssertionError
.
iex> assert_contains([1, 2, 3], [1, 3])
[1, 2, 3]
iex> assert_contains(%{a: 1, b: 2, c: 3}, %{a: 1, c: 3})
%{a: 1, b: 2, c: 3}
iex> assert_contains([1, 2, 3], 2)
[1, 2, 3]
@spec assert_eq( left :: any(), right :: any(), opts :: assert_eq_opts() | [assert_eq_opts()] ) :: any()
Asserts that the left
and right
values are equal. It returns the left
value unless the assertion fails,
or unless the :returning
option is used. As a special case, if the first argument is a string and the second
is a Regex, the comparison is done with the =~
operator instead of the ==
operator.
Style note: the authors prefer to use assert
in most cases, using assert_eq
only when the extra options
are helpful or when they want to make assertions in a pipeline.
iex> import Moar.Assertions
# prefer regular `assert` when `assert_eq` is not necessary
iex> assert Map.put(%{a: 1}, :b, 2) == %{a: 1, b: 2}
true
# works nicely with pipes
iex> %{a: 1} |> Map.put(:b, 2) |> assert_eq(%{a: 1, b: 2})
%{a: 1, b: 2}
# returns an arbitrary value instead of the left value
iex> map = %{a: 1, b: 2}
iex> map |> Map.get(:a) |> assert_eq(1, returning: map)
%{a: 1, b: 2}
# compares using a regex if `left` is a string and `right` is a Regex
iex> assert_eq "the length is 10cm", ~r/.*length is \d{2}cm/
left
and right
can be transformed by passing in one or more functions (optionally using the apply:
keyword).
If left
and right
are lists, all their values can be transformed using the map:
option.
iex> import Moar.Assertions
# apply a function
iex> assert_eq("hello", "heLLo", &String.downcase/1)
"hello"
# apply multiple functions (left to right)
iex> assert_eq("hello", "heLLo", [&String.downcase/1, &String.reverse/1])
"olleh"
# apply a function explicitly
iex> assert_eq("hello", "heLLo", apply: &String.downcase/1)
"hello"
# map all elements with a function
iex> assert_eq(["a", "B"], ["A", "b"], map: &String.downcase/1)
["a", "b"]
# combine apply and map (left to right)
iex> assert_eq(["a", "B", "C"], ["A", "b", "Z"], apply: &Enum.drop(&1, -1), map: &String.downcase/1)
["a", "b"]
If left
and right
are maps, only: <list>
will only consider the given keys, and except: <list>
will ignore
certain keys.
iex> import Moar.Assertions
# ignore one or more keys of a map
iex> assert_eq(%{a: 1, b: 2, c: 3}, %{a: 1, b: 100, c: 3}, except: [:b])
%{a: 1, b: 2, c: 3}
# only assert on one or more keys of a map
iex> assert_eq(%{a: 1, b: 2, c: 3}, %{a: 1, b: 100, c: 3}, only: [:a, :c])
%{a: 1, b: 2, c: 3}
If left
and right
are lists, their order can be ignored using :ignore_order
.
iex> import Moar.Assertions
# ignoring order when comparing lists
iex> assert_eq(["a", "b"], ["b", "a"], :ignore_order)
["a", "b"]
For inexact numerical assertions, within: <delta>
works like ExUnit.Assertions.assert_in_delta/4
, and
for inexact date and datetime assertions, within: {<delta>, <time-unit>}
asserts that left
and right
are within some duration of each other. See Moar.Duration
for more about time units, and also see
Moar.Assertions.assert_recent/2
. If left
and right
are strings, they are parsed as ISO8601 dates.
iex> import Moar.Assertions
# assert within a delta (this particular case could use ExUnit.Assertions.assert_in_delta/4).
iex> assert_eq(4/28, 0.14, within: 0.01)
0.14285714285714285
# assert within a time delta
iex> inserted_at = ~U[2022-01-02 03:00:00Z]
iex> updated_at = ~U[2022-01-02 03:04:00Z]
iex> assert_eq(inserted_at, updated_at, within: {10, :minute})
~U[2022-01-02 03:00:00Z]
# assert within a time delta when inputs are time strings
iex> inserted_at = "2022-01-02T03:00:00Z"
iex> updated_at = "2022-01-02T03:04:00Z"
iex> assert_eq(inserted_at, updated_at, within: {10, :minute})
"2022-01-02T03:00:00Z"
The following transformation shortcuts are supported:
:downcase
- ifleft
andright
are strings, converts them to lowercase before comparing:sort
- the same as:ignore_order
:squish
- ifleft
andright
are strings, trims the strings and replaces consecutive whitespace characters with a single space usingMoar.String.squish/1
before comparing:trim
- ifleft
andright
are strings, trims the strings usingString.trim/1
before comparing
iex> import Moar.Assertions
iex> assert_eq("FOO bar", "foo bar", :downcase)
"foo bar"
iex> assert_eq(" FOO bar ", "foo bar", [:downcase, :squish])
"foo bar"
The following options are deprecated:
ignore_order: <boolean>
- use:ignore_order
instead ofignore_order: true
ignore_whitespace: :leading_and_trailing
- use:squish
or:trim
insteadwhitespace: :squish
- use:squish
insteadwhitespace: :trim
- use:trim
instead
@spec assert_recent(DateTime.t() | NaiveDateTime.t() | binary(), Moar.Duration.t()) :: DateTime.t() | NaiveDateTime.t() | binary()
Asserts that datetime
is within recency
of now (in UTC), returning datetime
if the assertion succeeeds.
Uses assert_eq(datetime, now, within: recency)
under the hood.
datetime
can be aDateTime
, aNaiveDateTime
, or an ISO8601-formatted UTC datetime string.recency
is aMoar.Duration
and defaults to{10, :second}
.
iex> five_seconds_ago = Moar.DateTime.add(DateTime.utc_now(), {-5, :second})
iex> assert_recent five_seconds_ago
iex> twenty_seconds_ago = Moar.DateTime.add(DateTime.utc_now(), {-20, :second})
iex> assert_recent twenty_seconds_ago, {25, :second}
Asserts that a pre-condition and a post-condition are true after performing an action, returning the result of the action.
To use an anonymous function as the action, wrap it in parentheses and call it with .()
.
Examples
iex> {:ok, agent} = Agent.start(fn -> 0 end)
...>
iex> assert_that Agent.update(agent, fn s -> s + 1 end),
...> changes: Agent.get(agent, fn s -> s end),
...> from: 0,
...> to: 1
:ok
...>
iex> assert_that Agent.update(agent, fn s -> s + 1 end),
...> changes: Agent.get(agent, fn s -> s end),
...> to: 2
:ok
...>
iex> assert_that (fn -> Agent.update(agent, fn s -> s + 1 end) end).(),
...> changes: Agent.get(agent, fn s -> s end),
...> to: 3
:ok
Refute that a condition is changed after performing an action, returning the result of the action.
Examples
iex> {:ok, agent} = Agent.start(fn -> 0 end)
...>
iex> refute_that Function.identity(1),
...> changes: Agent.get(agent, fn s -> s end)
1
iex> refute_that Function.identity(5),
...> changes: %{a: 1}
5