DEV Community

Clean and reusable test helpers with Elixir macros

Unnawut Leepaisalsuwanna on September 28, 2019

Sometimes, seemingly redundant tests could serve as an assurance that our code works. While it's possible to abstract away the tests to a higher le...
Collapse
 
bliss_cs profile image
Suracheth Chawla • Edited

Thank you for introducing to this nice pattern.
By reading and trying the code I think that UserTest, in helper functions pattern, is missing an import to ExUnit.Assertions which contains assert function.

defmodule TestHelper do
  import  ExUnit.Assertions # missing import here

  def not_blank(schema, field) do
    {result, changeset} = schema.insert(%{field => nil})

    assert result == :error
    assert changeset.errors == [{field, {"can't be blank", [validation: :required]}}]
  end
end

defmodule UserTest do
  use ExUnit.Case
  import TestHelper

  describe "insert/1" do
    #...
    test "fails when given a blank name" do
      assert not_blank(User, :name)
    end
  end
end

defmodule AccountTest do
  use ExUnit.Case
  import TestHelper

  describe "insert/1" do
    #...
    test "fails when given a blank name" do
      assert not_blank(Account, :name)
    end
  end
end

Another thing I could think of that could think off is puttingassert in assert not_blank(schema, field) is a bit redundant here. I think we could rename not_blank/2 to assert_not_blank/2.

how do think of my thoughts? Thank you for posting nice patterns.

Collapse
 
unnawut profile image
Unnawut Leepaisalsuwanna

Updated the missing import. Thanks!

assert_not_blank/2 is a great idea since its error message can be customized to fit the assertion. assert not_blank(schema, field) on the otherhand would produce an unhelpful "Expected truthy, got false" error message.