AssertIdentity - ExUnit assertions for comparing data structures by identity

I’m pleased to announce the initial release of AssertIdentity. It’s a small helper library for ExUnit that provides assertions useful for comparing data structures by identity.

AssertIdentity really shines in applications that leverage Ecto. Consider the following:

def MyApp.PostTest do
  use MyApp.DataCase

  test "list_posts/0 returns all posts" do
    post = insert(:post)
    assert Posts.list_posts() == [post]
    assert_ids_match(Posts.list_posts(), [post])
  end
end

The first assertion fails when using factories that, for example, insert associations. (That’s because on the left-hand side you’ll have Ecto.Association.NotLoaded for the association values but on the right-hand side you’ll have a real association struct.)

The assert_ids_match/2 assertion passes because it instead plucks the :id key from each struct and compares those values (instead of an identity comparison on the whole struct).

This started as a single helper in one application but we kept pulling it into every Elixir app we’ve worked on so we decided to release it. Perhaps you’ll find it useful too!

Check out the docs for more examples and options on how to customize the identity assertion to your needs! And, of course, feel free to open bug reports or enhancement PRs on GitHub.

Links:

1 Like

Historically I have either rolled my own local syntax for this using vanilla Elixir, or where possible, used the assertions library. I’d reach for assert_lists_equal/3 if I wasn’t validating order, or wrapping individual assert_maps_equal/3 or assert_structs_equal/3 in Enum calls if order between left/right is significant. I like how general/composable assertions is, and that it allows me to be precise about what inner values I care about, so I can omit things like unloaded associations or timestamps. Of course, it’s not zero-downside to casually adopt since it’s an external dependency and macro-based.

This library would essentially be:

assert_lists_equal(Posts.list_posts(), [post], &assert_structs_equal(&1, &2, [:id]))
3 Likes

Yep, totally possible to do this without the library. We started by implementing it in vanilla Elixir in one project, but we ended up re-implementing it in every project we were working on, so we just wrapped it up and can now include it easily. Definitely can also compose it up with the Assertions library as well! So there are many options for achieving the same thing, this is perhaps just a shortcut in case, like us, you end up using this a lot.

1 Like