AssertMatch (assert_match v1.1.0)

Provides pipe-friendly assert_match/2

Link to this section Summary

Functions

Pipe-friendly equality/matching assertion.

Link to this section Functions

Link to this macro

assert_match(subject, pattern)

(macro)
@spec assert_match(any(), Macro.t()) :: any()

Pipe-friendly equality/matching assertion.

Performs assert/1 with:

  • =~ for Regex patterns
  • match?/2 for patterns with guards
  • = for other patterns

For the third variant, it can utilize bindings inside the pattern from outside!

%{key: 1}
|> assert_match(%{key: value})

assert value == 1

extraction-of-pinned-function-calls

Extraction of pinned function calls

Elixir's ^/1 (pin operator) usually does not allow runtime function calls, and only accepts previously bound user variables.

However, this macro "extracts" runtime function calls on pins in the pattern and bind their results to temporary variables named pinned__<n> (where <n> is unique integer) so that you can actually write function calls with pins! (Just like you do with Ecto.Query)

With this you are now able to write test expressions like so:

conn
|> post("/some/api")
|> json_response(200)
|> assert_match(%{
  "success" => true,
  "id" => ^context.some_fixture.id,
  "bytesize" => ^byte_size(context.some_fixture.contents)
})

You cannot nest pinned expressions. See test/assert_match_test.exs for more usages.

guards

Guards

Guards are supported, but with limitations: if guards are used, bindings inside patterns cannot be used from outside.

%{key: 1}
|> assert_match(map when is_map(map))
# => Passes

assert map == %{key: 1}
# => error: undefined variable "map"

Related: bindings inside patterns that are NOT used in the guards are warned as unused.

%{key: 1}
|> assert_match(%{key: value} = map when not is_map_key(map, :nonkey))
# => warning: variable "value" is unused (if the variable is not meant to be used, prefix it with an underscore)

This is a relatively new limitation introduced in Elixir 1.18, as a side-effect of this change.