Reputation: 2155
Given the following code:
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
The doctest
fails with:
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)
Is there a way of specifying that the "Units"
value is randomly generated? It looks like I'm following the way Enum.random
is doctested
Upvotes: 0
Views: 587
Reputation: 222128
Enum.random
's doctest is explicitly setting a seed value for the test, which makes the result of future calls to :rand
functions deterministic.
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]
The person who wrote the tests most likely ran the functions once to check what values are returned after those seed values are set and then put them in the doctest. Unless the inner workings of :rand
change, those seeds will keep producing the same values, which is good enough for doctests (you can always fix the tests if it breaks in future versions of Erlang).
So, to fix your doctest, you should execute this code once in iex (you can change the seed values if you want):
:rand.seed(:exsplus, {101, 102, 103})
Pullapi.Workout.pullup_set(20, 60, 5)
And then hardcode the returned values in your doctest. Your tests should now pass until Erlang's rand module's internals change.
Upvotes: 3