Parameterized ExUnit tests
In ExUnit, it is not immediately obvious how to do the same “test” using different parameters.
It can be tedious to write individual tests for each required field asserting the validation. It’s also difficult for future-you to determine if you have complete coverage.
The cheating way
Remove the all the required fields from the source map before calling changeset
and make one massive assert
The better way
The solution I use here is to set the @tag
test attribute as two properties of the test.
The first @tag field: field_name
is the property I’m testing against
The second @tag message_attr: %{attr_name => nil}
is the value to assign that field before running the test.
You’ll see that these @tag
values are available in the test context
by the given tag name
[
{:entity_name, :entity_name},
{:entity_uuid, :team_uuid}
]
|> Enum.each(fn {field_name, attr_name} ->
@tag field: field_name
@tag message_attr: %{attr_name => nil}
test "when `#{field_name}` missing, invalid ... required", context do
message = TestMessageHelpers.market_message(context.message_attr)
%Changeset{valid?: false} = changeset = Subject.changeset(%Subject{}, message)
assert changeset.errors == [{context.field, {"can't be blank", [validation: :required]}}]
end
end)
Tweet