-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
assert_maps_equal should have a default third argument #30
Comments
Not sure if this is related, but I came here because something that I struggle with a lot is wanting to be able to check if a list of results match a set of subsets because one or more keys will change from test-to-test (like an ID or a timestamp). For example, if I have a function
I could do a couple of different things:
Or maybe:
But it would be nice to maybe have something like:
One question is if each element of the list should match according to It might look something like this: def assert_lists_match([], []), do: true
def assert_lists_match(records, asserted_maps) when length(records) != length(asserted_maps), do: false
def assert_lists_match(records, [asserted_map | rest_of_assertion]) do
index = Enum.find_index(records, fn record ->
Enum.all?(asserted_map, fn {asserted_key, asserted_value} ->
record[asserted_key] == asserted_value
end)
end)
if index do
assert_lists_match(List.delete_at(records, index), rest_of_assertion)
else
false
end
end |
I made a local function for myself to get on with what I was doing and I have some tests behind it now, so my draft code changed some. I needed to take care of the problem where matching records get exhausted early, so it needs to be open to looking through the whole search space. Also, I put the assertion-part as the first argument since that seemed to be how the def assert_lists_match([], []), do: true
def assert_lists_match(asserted_maps, records) when length(asserted_maps) != length(records), do: false
def assert_lists_match([subset_map | rest_of_assertion], records) do
records
|> Enum.with_index()
|> Enum.any?(fn {record, index} ->
matches_subset?(subset_map, record) &&
assert_lists_match(rest_of_assertion, List.delete_at(records, index))
end)
end
defp matches_subset?(subset_map, record) do
Enum.all?(subset_map, fn {asserted_key, asserted_value} ->
Map.get(record, asserted_key) == asserted_value
end)
end My tests: defmodule MyApp.TestHelpersTest do
use ExUnit.Case, async: true
alias MyApp.TestHelpers
defmodule TestStruct do
defstruct [:name, :city]
end
test "empty lists" do
assert TestHelpers.assert_lists_match([], [])
# Expected to have one element
refute TestHelpers.assert_lists_match([%{name: "bar"}], [])
# Expected to be empty
refute TestHelpers.assert_lists_match([], [%{name: "bar"}])
refute TestHelpers.assert_lists_match([], [%TestStruct{name: "bar"}])
end
test "single matches" do
assert TestHelpers.assert_lists_match([%{name: "bar"}], [%{name: "bar"}])
assert TestHelpers.assert_lists_match([%{name: "bar"}], [%TestStruct{name: "bar"}])
assert TestHelpers.assert_lists_match([%{name: "bar"}], [%{name: "bar", city: 1}])
assert TestHelpers.assert_lists_match([%{name: "bar"}], [%TestStruct{name: "bar", city: 1}])
# Wrong value
refute TestHelpers.assert_lists_match([%{name: "bar"}], [%{name: "biz", city: 1}])
refute TestHelpers.assert_lists_match([%{name: "bar"}], [%TestStruct{name: "biz", city: 1}])
# Wrong key
refute TestHelpers.assert_lists_match([%{name: "bar"}], [%{biz: "bar", city: 1}])
# Missing key
refute TestHelpers.assert_lists_match([%{name: "bar"}], [%{city: 1}])
refute TestHelpers.assert_lists_match([%{name: "bar"}], [%TestStruct{city: 1}])
end
test "multiple matches" do
values = [
%{name: "John"},
%{name: "Jane"},
%{name: "Johan"}
]
# Testing that this works, but this isn't the best way to use this function
assert TestHelpers.assert_lists_match([%{}, %{}, %{}], values)
assert TestHelpers.assert_lists_match([%{name: "John"}, %{}, %{}], values)
assert TestHelpers.assert_lists_match([%{}, %{name: "John"}, %{}], values)
assert TestHelpers.assert_lists_match([%{}, %{}, %{name: "John"}], values)
for _ <- 1..10 do
assert TestHelpers.assert_lists_match(Enum.shuffle([%{name: "Jane"}, %{name: "Johan"}, %{name: "John"}]), values)
end
subsets =
for i <- 1..200 do
%{name: Faker.Name.name(), city: Faker.Address.city()}
end
for _ <- 1..10 do
values =
subsets
|> Enum.map(fn record ->
record
|> Map.put(:id, Faker.UUID.v4())
|> Map.put(:country, Faker.Address.En.country())
end)
assert TestHelpers.assert_lists_match(Enum.shuffle(subsets), values)
end
end
end |
I think this
assertions/lib/assertions.ex
Line 333 in 8b353fd
if nothing is passed as keys, assume exact equivalency
assert_lists_equal Map.keys(left), Map.keys(right)
at the beginningif
:left
is passed as third argument, should convert toMaps.keys(left)
and equivalently for rightOr something along those lines. What do you think? Would a PR in this sense be useful/appreciated?
The text was updated successfully, but these errors were encountered: