给出以下代码:
defmodule Pullapi.Workout do
import Pullapi.Numbers
@moduledoc """
Functions that generate a workout representation
"""
@doc """
Returns a pullup set defined by the number of `max_reps` a user can do, a `percentage`, and the
number of maximum additional or decremented reps, `rep_bound`.
## Examples
iex> Pullapi.Workout.pullup_set(20, 60, 5)
%{"Action" => "Pullups", "Units" => "14"}
"""
@spec pullup_set(integer, integer, integer) :: map()
def pullup_set(max_reps, percentage, rep_bound) do
median = max_reps * (percentage / 100)
unit_range = Pullapi.Numbers.median_range(round(median), rep_bound)
units = Enum.random(unit_range)
%{"Action" => "Pullups", "Units" => "#{units}"}
end
end
doctest
失败了:
1) test doc at Pullapi.Workout.pullup_set/3 (1) (PullapiTest)
test/pullapi_test.exs:4
Doctest failed
code: Pullapi.Workout.pullup_set(20, 60, 5) === %{"Action" => "Pullups", "Units" => "14"}
left: %{"Action" => "Pullups", "Units" => "8"}
stacktrace:
lib/pullapi/workout.ex:13: Pullapi.Workout (module)
有没有办法指定"Units"
值是随机生成的?看起来我正在关注the way Enum.random
is doctested
答案 0 :(得分:2)
Enum.random
的doctest明确设置了测试的种子值,这使得将来调用:rand
函数的结果具有确定性。
iex(1)> for _ <- 1..10 do
...(1)> :rand.seed(:exsplus, {101, 102, 103})
...(1)> Enum.random([1, 2, 3])
...(1)> end
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
编写测试的人最有可能运行一次函数来检查在设置种子值之后返回的值,然后将它们放入doctest中。除非:rand
的内部工作方式发生变化,否则这些种子将继续产生相同的值,这对于doctests来说已经足够了(如果它在Erlang的未来版本中断开,你可以随时修复测试)。
因此,要修复doctest,您应该在iex中执行一次此代码(如果需要,可以更改种子值):
:rand.seed(:exsplus, {101, 102, 103})
Pullapi.Workout.pullup_set(20, 60, 5)
然后在doctest中对返回的值进行硬编码。你的测试现在应该通过,直到Erlang的rand模块的内部结构发生变化。