FlowAssertions.AssertionA (Flow Assertions v0.7.1) View Source

Assertions used to test other assertions.

These assertions do not work on the textual output of an assertion error. Instead, they inspect the internals of the ExUnit.AssertionError structure. Here is an example:

  assertion_fails(
    "some text"
    [left: "something"],
    fn -> 
      assert_no_value(data, :something_field)
    end)

The first argument ("some text") describes the expected :message field. The next line describes the value expected in the :left field.

As far as I know, the ExUnit.AssertionError isn't guaranteed to stay stable, so beware. As of August 2020, these are the fields you can use:

defexception left: @no_value,
             right: @no_value,
             message: @no_value,
             expr: @no_value,
             args: @no_value,
             doctest: @no_value,
             context: :expr

Link to this section Summary

Functions

Check if an assertion fails in the expected way.

Link to this section Functions

Link to this function

assertion_fails(message, kws \\ [], f)

View Source

Check if an assertion fails in the expected way.

The assertion must be wrapped in a function:

    fn -> 
      assert_no_value(data, :something_field)
    end)

A typical call looks like this:

   assertion_fails(
      "some text"
      [left: "something"],
      fn -> ... end)

The first argument is the expected :message field in the ExUnit.AssertionError structure.

The second argument is a keyword list describing the other fields of the AssertionError structure.

The :message value and the other field values will be compared using FlowAssertions.MiscA.good_enough?/2. So, for example, the check of the error message need not be exact:

   assertion_fails(
      ~r/some text.*final text/,
      ...

If the assertion correctly fails, the return value is the ExUnit.AssertionError the assertion created.

Link to this function

assertion_fails_for(under_test, left, message, kws \\ [])

View Source

A variant of assertion_fails/3 that is useful in chaining.

This assertion is tailored for a function that is passed through a pipeline and exposed to different arguments at each stage:

  msg = "..."

  (&error_content/1)                    # <= parentheses are important
  |> assertion_fails_for(:error, msg)
  |> assertion_fails_for({:ok, "content"}, msg)

In the above case, FlowAssertions.MiscA.error_content/1 is exposed to two different values. Both should cause an ExUnit.AssertionError with a particular :message.

A third argument could describe other ExUnit.AssertionError fields, as in assertion_fails/3.

Note the parentheses around error_content/1. They are required by Elixir's precedence rules: & binds more loosely than |>. If you leave the parentheses off, the expression turns into a single function that's never executed - meaning that the test can never fail, no matter how broken the code is.