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

Builders that create functions tailored to tabular tests.

Here are some tabular tests for how Previously.parse copes with one of its keyword arguments:

[insert:  :a                  ] |> expect.([een(a: Examples)])
[insert: [:a, :b      ]       ] |> expect.([een(a: Examples), een(b: Examples)])
[insert: [:a,  b: List]       ] |> expect.([een(a: Examples), een(b: List)])

[insert: :a, insert: [b: List]] |> expect.([een(a: Examples), een(b: List)])

[insert: een(a: Examples)     ] |> expect.([een(a: Examples)])

The expect function above was created with:

expect = TabularA.run_and_assert(
  &(Pnode.Previously.parse(&1) |> Pnode.EENable.eens))

There is also a function that allows assertions about exceptions to be written in a tabular style:

raises = TabularA.run_for_exception(&case_clause/2)
[3, 3] |> raises.(CaseClauseError)

For more on this style, see "Tabular tests in Elixir".

You can find similar builders in FlowAssertions.Define.Tabular. They produce functions used to test assertions (like the ones in this package).

Beware the typo

I make this kind of typo a lot:

[2, 2] |> expect("The sum is 4")

There should be a period after expect. The result (as of Elixir 1.11) is

** (CompileError) test.exs:42: undefined function expect/2

Link to this section Summary

Functions

Hide repeated code inside an expect function, allowing concise tabular tests.

A more concise version of ExUnit.Assertions.assert_raise/3, suitable for tabular tests.

Return the results of both run_and_assert and run_for_exception.

Link to this section Functions

Link to this function

run_and_assert(result_producer, asserter \\ &MiscA.assert_equal/2)

View Source

Hide repeated code inside an expect function, allowing concise tabular tests.

The first argument is a function that generates a value. It may just be the function under test:

expect = TabularA.run_and_assert(&Enum.take/2)

Quite often, however, it's a function that does some extra work for each table row. For example, the following extracts just the part of the result that needs to be checked. Because of that, the table is less cluttered.

expect = TabularA.run_and_assert(
  &(Pnode.Previously.parse(&1) |> Pnode.EENable.eens))

Because the above function has a single argument, expect is called like this:

:a |> expect.([een(a: Examples)])

Functions that take two or more arguments need them to be enclosed in a list or tuple:

[:a, :b] |> expect.([een(:a, b: Examples)])
{:a, :b} |> expect.([een(:a, b: Examples)])

(I use tuples when some of the arguments are lists. It's easier to read.)

By default, correctness is checked with ===. You can override that by passing in a second function:

expect = TabularA.run_and_assert(
  &Common.FromPairs.extract_een_values/1,
  &assert_good_enough(&1, in_any_order(&2)))

In the above case, the second argument is a function that takes both a computed and an expected value. You can instead provide a function that only takes the computed value. In such a case, I typically call the resulting function pass:

pass = TabularA.run_and_assert(
  &case_clause/1,
  &(assert &1 == "one passed in"))

1 |> pass.()

Beware: a common mistake is to use a predicate like &(&1 == "one passed in"). Without an assertion, the generated pass function can never fail.

Link to this function

run_for_exception(result_producer)

View Source

A more concise version of ExUnit.Assertions.assert_raise/3, suitable for tabular tests.

A typical use looks like this:

"some error value" |> raises.("some error message")

Creation looks like this:

raises = TabularA.run_for_exception(&function_under_test/1)

As with FlowAssertions.TabularA.run_and_assert/2, multiple arguments are passed in a list or tuple:

[-1, 3] |> raises.(~r/no negative values/)

As shown above, the expected message may be matched by a String or Regex. You can also check which exception was thrown:

[3, 3] |> raises.(CaseClauseError)

If you want to check both the type and message, you have to enclose them in a list:

[3, 3] |> raises.([CaseClauseError, ~R/no case clause/])

Note that you can put multiple regular expressions in the list to check different parts of the message.

The generated function returns the exception, so it can be piped to later assertions:

[3, 3] |> raises.([CaseClauseError, ~R/no case clause/])
       |> assert_field(term: [3, 3])
Link to this function

runners(result_producer, asserter \\ &MiscA.assert_equal/2)

View Source

Return the results of both run_and_assert and run_for_exception.

{expect, raises} = TabularA.runners(&case_clause/2)

The optional second argument is passed to expect.