首页 > 解决方案 > Elixir:将混合项目配置为始终将字符列表打印为列表?

问题描述

在测试我的 Phoenix 应用程序时,我经常遇到需要比较预期记录 ID 列表和实际记录 ID 列表的情况。错误解释起来很乏味,因为 Elixir 一直将整数列表打印为字符列表,所以我的测试输出如下所示:

     Assertion with == failed
     code:  assert H.sort(Enum.map(list1, &(&1.id()))) == H.sort(Enum.map(list2, &(&1.id())))
     left:  'stu'
     right: 'st'

这促使我重写我的测试以避免比较整数列表,这是可以容忍的,但只是耸耸肩并用这样的语言寻找解决方法是一种耻辱。所以我想知道是否有办法告诉 Elixir/Mix始终将整数列表打印为列表,而不是 charlists/charstrings。我编写了 Ruby 风格的 Elixir,而且我几乎从不使用 charlists,对我来说,它们主要是一个可以解决的问题。

感谢这个答案,我知道有一种方法可以将 IEx 配置为始终将整数列表打印为列表。有没有办法在 Mix 中这样做,或者在 Elixir 本身中全局这样做,所以mix test会采用这种行为吗?

标签: elixir

解决方案


charlists 的“人性化”可能是 Elixir 中最令人困惑的问题之一。正如@Aleksei指出的那样,这是不可配置的ExUnit(尽管您可以通过iex添加文件来配置)。IEx.configure(inspect: [charlists: :as_lists]).iex.exs

但是,您不需要重写测试。请记住,打印值的方式只是数据的视图。它不影响数据的存储方式

您的示例断言失败,因为'stu'is not equal to 'st'just as [115, 116, 117]is not equal to [115, 116]

看下面的代码:

iex> [115, 116, 117] === 'stu'
true

左侧和右侧是 100% 完全等效的。单引号仅允许人们更轻松地输入数据。

在您的特定情况下,您可能需要查看MapSet,特别是如果您的 ID 列表是唯一的。然后,您可以避免在比较之前进行尴尬/脆弱的排序。使用MapSet,您可以只比较两组是否相等。例如:

expected_ids = MapSet.new([115, 116, 117])
actual_ids = MapSet.new(some_function_output)

assert MapSet.equal?(actual_ids, expected_ids)

这可能有助于避免冗长的跟踪由 charlists 引起的错误。在您的情况下,另一种选择可能是在映射期间将整数转换为字符串,例如Enum.map(list1, fn x -> to_string(x.id) end)


推荐阅读