A test assertion library for Erlang, by WhatsApp.
assert is an Erlang library which enhances how Erlang errors and
assertions are rendered, making it easier for developers to understand
what is wrong when an error occurs. The library includes:
| File | Description |
|---|---|
| assert.hrl | An improved, compatible, versions of Erlang/OTP stdlib's assert macros. |
| wa_diff.erl | A structural diffing library for Erlang, inspired by Elixir's ExUnit.Assertions library. |
| wa_blame.erl | Exception blaming for Erlang, inspired by Elixir's Exception behaviour. |
The assert library provides an assert.hrl header file which can be
used as a drop-in replacement for the Erlang/OTP one, part of
stdlib.
Let's look at a sample module causing an assertion failure:
-module(assert_sample).
-include_lib("stdlib/include/assert.hrl").
-export([assert/0]).
assert() ->
A = a(),
B = b(),
?assertEqual(A, B).
a() ->
#{a => 1, b => [{b, 1}, {b, 3}], c => 3}.
b() ->
#{a => 1, b => [{b, 1}, {b, 2}, {b, 3}], c => 3}.Let's compile run the code:
> c(assert_sample).
> assert_sample:assert().
Even if the above one is a trivial example, it still takes some effort to realize where the problem is:
Let's replace the -include_lib directive to use the assert library instead:
-include_lib("assert/include/assert.hrl").And run the code again:
> c(assert_sample).
> assert_sample:assert().
Much easier, isn't it? 🌈
wa_diff is a structural diffing library for Erlang. Inspired by Elixir's
ExUnit.Assertions and
powered by the diffy implementation of
Neil Fraser's match-and-patch algorithm,
it provides a way to diff Erlang data types such as maps, records, lists, tuples and more.
The main entry point is the compute/2 function which, given two values, produces left and right parts:
> #{left := Left, right := Right, equivalent := Equivalent} = wa_diff:compute(#{one => 1, two => 2}, #{one => 1, two => 3}).
#{left =>
{map,[],[{one,1},{two,#{contents => [{true,<<"2">>}]}}]},
right =>
{map,[],[{one,1},{two,#{contents => [{true,<<"3">>}]}}]},
equivalent => false}Each part can then be rendered via the to_diff/3 function. For example:
> wa_diff:to_diff(Left, ~"-", ~"-").
{ok,"#{one => 1, two => -2-}"}
> wa_diff:to_diff(Right, ~"+", ~"+").
{ok,"#{one => 1, two => +3+}"}Records can be pretty-printed by providing a third argument to the compute/3 function,
i.e. the module containing the record definition to be used for pretty-printing.
[wa_blame] implements "Exception Blaming" for Erlang errors, enhancing the stacktrace for errors.
For example, during a function clause error, wa_blame can figure out why each clause did not match.
Given a sample module containing the following function definition:
my_function({X, Y}) when is_integer(X), is_list(Y) -> ok;
my_function({X, Y}) when is_list(X), is_integer(Y) -> ok;
my_function({X, Y, Z}) when is_integer(X), is_integer(Y), is_integer(Z) -> ok;
my_function({X, Y}) when is_list(X), is_list(Y) -> ok.A typical function clause error would look like:
> sample:my_function({1, [], 1}).
** exception error: no function clause matching sample:my_function({1,[],1}) (sample.erl, line 6)We can intercept the error via a try/catch and enhance it via wa_blame:
> {ok, Message} = try
sample:my_function({1, [], 1})
catch Error:Reason:Stacktrace ->
wa_blame:format_blame(Reason, Stacktrace)
end.To add assert to your rebar3 project, simply add it to the deps in your rebar.config:
{deps, [
{assert, {git, "http://github.com/whatsapp/assert.git"}}
]}.
assert requires Erlang/OTP 26.
assert is Apache 2.0 licensed, as found in the LICENSE file.
Copyright © Meta Platforms, Inc


