Current section
Files
Jump to
Current section
Files
lib/struct_assert.ex
defmodule StructAssert do
@moduledoc """
A useful tool for testing sturct and map in Elixir.
"""
defmacro __using__(_opts) do
quote do
import StructAssert, only: [assert_subset: 2]
end
end
@doc """
assert only a part of struct and map.
defmodule MyStruct do
defstruct a: 1, b: 1, z: 10
end
defmodule Example
use ExUnit.Case
use StructAssert
test "example" do
assert_subset(%MyStruct{}, [a: 1, b: 2])
# code: assert_subset(%MyStruct{}, [a: 1, b: 2])
# left: %{a: 1, b: 1, z: 10}
# right: %{a: 1, b: 2, z: 10}
assert_subset(%MyStruct{}, [a: 1, b: &is_atom(&1)])
# code: assert_subset(%MyStruct{}, [a: 1, b: &(is_atom(&1))])
# left: %{a: 1, z: 10, b: 1}
# right: %{a: 1, z: 10, b: &:erlang.is_atom/1}
end
end
"""
defmacro assert_subset(got, expect) do
expr = build_expr_for_error_message(got,expect)
quote do
import ExUnit.Assertions
got_map = StructAssert.got_value_to_map(unquote(got))
expect_map = StructAssert.expect_value_to_map(unquote(expect))
resolver = fn
(_, original, override) when is_function(original) and is_function(override) -> DeepMerge.continue_deep_merge
(_, original, override) when is_function(override) ->
case override.(original) do
true -> original
_ -> override
end
(_, _original, _override) -> DeepMerge.continue_deep_merge
end
expect = DeepMerge.deep_merge(got_map,expect_map, resolver)
assert got_map == expect,
expr: unquote(expr),
left: got_map,
right: expect
end
end
@doc """
deprecated
"""
defmacro assert_subset?(got, expect) do
quote do
StructAssert.assert_subset(unquote(got),unquote(expect))
end
end
def build_expr_for_error_message(got,expect) do
got_var_name = got |> Macro.expand(__ENV__) |> Macro.to_string
expect_var_name = expect |> Macro.expand(__ENV__) |> Macro.to_string
"assert_subset(#{got_var_name}, #{expect_var_name})"
end
defmacro got_value_to_map(got) do
quote do
case unquote(got) do
%_{} -> Map.from_struct(unquote(got))
%{} -> unquote(got)
end
end
end
defmacro expect_value_to_map(expect) do
quote do
case unquote(expect) do
%{} -> unquote(expect)
is_list -> Enum.into(unquote(expect), %{})
end
end
end
end