Connecting Elixir to Salesforce (Part 1)
Most of the time we are connecting to Salesforce via an Elixir API server written in Phoenix that receives requests from a Vue.js front-end to send to or retrieve data from Salesforce.
Elixir unit testing is fantastic, especially with the recently-added colored diff messages, but often it can get cumbersome to compare collections of Ecto models.
Say you have a unit test that compares a list of structs.
# %User{city: nil, email: nil, first_name: nil, id: nil, last_name: nil, password: nil, state: nil, zipcode: nil}
users = [u_1, u_2, u_3, u_4, u5]
expected = [u_5, u_4, u_3, u_2, u_1]
assert users == expected
A simple list of 5 users out of order can blow up like
1) test the truth (TuplizeTest)
test/tuplize_test.exs:6
Assertion with == failed
code: users == expected
lhs: [%User{city: "48015 Daron Knolls", email: "[email protected]", first_name: "Dallas", id: 974, last_name: "Rosenbaum", password: "8550008389", state: "FL", zipcode: "64063-1288"}, %User{city: "26 Wilderman Path", email: "[email protected]", first_name: "Jude", id: 370, last_name: "Hagenes", password: "2757565087", state: "AZ", zipcode: "76720"}, %User{city: "88 Spinka Key", email: "[email protected]", first_name: "Estefania", id: 638, last_name: "Schmeler", password: "8238362474", state: "RI", zipcode: "09096"}, %User{city: "5 Joe Viaduct", email: "[email protected]", first_name: "Rachael", id: 558, last_name: "Hoppe", password: "2162383519", state: "GA", zipcode: "42240"}, %User{city: "86947 Monica Knolls", email: "[email protected]", first_name: "Chanel", id: 79, last_name: "Collier", password: "8587846213", state: "AL", zipcode: "97504-5221"}]
rhs: [%User{city: "86947 Monica Knolls", email: "[email protected]", first_name: "Chanel", id: 79, last_name: "Collier", password: "8587846213", state: "AL", zipcode: "97504-5221"}, %User{city: "5 Joe Viaduct", email: "[email protected]", first_name: "Rachael", id: 558, last_name: "Hoppe", password: "2162383519", state: "GA", zipcode: "42240"}, %User{city: "88 Spinka Key", email: "[email protected]", first_name: "Estefania", id: 638, last_name: "Schmeler", password: "8238362474", state: "RI", zipcode: "09096"}, %User{city: "26 Wilderman Path", email: "[email protected]", first_name: "Jude", id: 370, last_name: "Hagenes", password: "2757565087", state: "AZ", zipcode: "76720"}, %User{city: "48015 Daron Knolls", email: "[email protected]", first_name: "Dallas", id: 974, last_name: "Rosenbaum", password: "8550008389", state: "FL", zipcode: "64063-1288"}]
stacktrace:
test/tuplize_test.exs:22: (test)
Wouldn't it be better if we could limit the number of attributes compared? Something like a list of ids and emails?
Drop this into your test/test_helpers.exs
defmodule Compare do
def tuplize(model, attrs \\ [])
def tuplize(model, attrs) when is_list(model) do
Enum.map(model, fn(x) -> tuplize(x, attrs) end)
end
def tuplize(model, attrs) do
attrs
|> Enum.map(fn(x) ->
case x do
x when is_function(x) -> x.(model)
_ -> Map.from_struct(model)[x]
end
end)
|> List.to_tuple
end
end
Update your test.
import Compare
args = [:id, :email]
users = [u_1, u_2, u_3, u_4, u5]
expected = [u_5, u_4, u_3, u_2, u_1]
assert tuplize(users, args) == tuplize(expected, args)
Run your test again. The output is much cleaner.
1) test the truth (TuplizeTest)
test/tuplize_test.exs:6
Assertion with == failed
code: tuplize(users, args) == tuplize(expected, args)
lhs: [{441, "[email protected]"}, {569, "[email protected]"}, {573, "[email protected]"}, {131, "[email protected]"}, {231, "[email protected]"}]
rhs: [{231, "[email protected]"}, {131, "[email protected]"}, {573, "[email protected]"}, {569, "[email protected]"}, {441, "[email protected]"}]
stacktrace:
test/tuplize_test.exs:23: (test)
Tuplize is very simple, fetching the atom attributes from the structs it is given and returning a list of neatly contained tuples. Tuplize can even execute anonymous functions on the structs, allowing for things like full name comparisons.
import Compare
args = [:id, fn(user) -> "#{user.first_name} #{user.last_name}" end]
users = [u_1, u_2, u_3, u_4, u5]
expected = [u_5, u_4, u_3, u_2, u_1]
assert tuplize(users, args) == tuplize(expected, args)
1) test the truth (TuplizeTest)
test/tuplize_test.exs:6
Assertion with == failed
code: tuplize(users, args) == tuplize(expected, args)
lhs: [{472, "Saul Schmeler"}, {769, "Janick Ruecker"}, {680, "Merl Rempel"}, {478, "Katheryn Weimann"}, {378, "Albert Conroy"}]
rhs: [{378, "Albert Conroy"}, {478, "Katheryn Weimann"}, {680, "Merl Rempel"}, {769, "Janick Ruecker"}, {472, "Saul Schmeler"}]
stacktrace:
test/tuplize_test.exs:23: (test)
Happy unit testing!