随机生成值的文档测试
doctests for randomly generated values
给定以下代码:
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
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 的 运行d 模块的内部结构发生变化。
给定以下代码:
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
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 的 运行d 模块的内部结构发生变化。