【问题标题】:Elixir doctest fails for function that returns random valuesElixir doctest 对于返回随机值的函数失败
【发布时间】:2018-07-29 04:11:35
【问题描述】:

我在 Elixir 中有一个函数,可以在列表中生成三个随机 RGB 元组。

defmodule Color do



  @doc """
  Create three random r,g,b colors as a list of three tuples

  ## Examples

      iex> colors = Color.pick_color()
      iex> colors
      [{207, 127, 117}, {219, 121, 237}, {109, 101, 206}]

  """
      def pick_color() do
        color = Enum.map((0..2), fn(x)->
          r = Enum.random(0..255)
          g = Enum.random(0..255)
          b = Enum.random(0..255)
          {r, g, b}
        end)
end

当我运行我的测试时,我的 doctests 失败了。生成的元组列表与我的 doctest 中定义的不同。如何为返回随机值的函数编写文档测试?

【问题讨论】:

  • 你不能。您只能对纯函数进行 doctest。
  • @JustinWood 您可以通过设置种子值使Enum.random 具有确定性(请参阅我的答案)。 :)
  • 您也可以(至少现在)在 doctests 中使用模式匹配:iex> [_a, _b, {_r, 121, _b}] = Color.pick_color(),只是不要在后面的行中放置预期的返回值。万一出现错误,测试输出也将得到完善。

标签: elixir ex-unit


【解决方案1】:

要使用 doctest 测试函数,您必须能够预测函数的输出。在这种情况下,您无法预测函数的输出。


但是您可以通过常规测试来测试您的功能。

这是一个测试,可以确保 Color.pick_color() 使用模式匹配生成 3 个元组的列表:

test "pick color" do
  [{_, _, _}, {_, _, _}, {_, _, _}] = Color.pick_color()
end

您还可以检查每个值是否介于0255 之间等。

【讨论】:

  • 我确实回到了常规测试。但是感谢您解释文档测试的限制:)
【解决方案2】:

您可以通过设置:rand 的随机数生成器的种子来使随机函数具有确定性。 This is also how Enum.random/1 is tested in Elixir.

首先,打开iex,将当前进程的种子设置为任意值:

iex> :rand.seed(:exsplus, {101, 102, 103})

然后,在iex 中运行您的函数

iex> Color.pick_color()

现在只需将此值与:rand.seed 调用一起复制到您的文档测试中。通过显式设置种子,您将从 :rand 模块中的函数获得相同的值,而 Enum.random/1 在内部使用 :rand

iex(1)> :rand.seed(:exsplus, {1, 2, 3})
iex(2)> for _ <- 1..10, do: Enum.random(1..10)
[4, 3, 8, 1, 6, 8, 1, 6, 7, 7]
iex(3)> :rand.seed(:exsplus, {1, 2, 3})
iex(4)> for _ <- 1..10, do: Enum.random(1..10)
[4, 3, 8, 1, 6, 8, 1, 6, 7, 7]
iex(5)> :rand.seed(:exsplus, {1, 2, 3})
iex(6)> for _ <- 1..10, do: Enum.random(1..10)
[4, 3, 8, 1, 6, 8, 1, 6, 7, 7]

【讨论】:

  • 令人印象深刻的哈哈。谢谢你。我一定会对此进行更多研究。
猜你喜欢
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 1970-01-01
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多