Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting seed and using random numbers in ExUnit test cases

Tags:

random

elixir

I have a test case that needs to use random integer, so I have:

test "test with random integer" do      
  IO.inspect :random.uniform(10)
  assert true
end

This always prints 4 when I run it, even though I can see different seeds in console output:

Randomized with seed 197796
...
Randomized with seed 124069

I know I should use :random.seed/1 or :random.seed/3. I want to use the same seed as is printed at the end of test output. This way if my test fails I can replicate it with

mix test --seed 124069

I can't do that if I am using :random.seed(:erlang.now) for example.

How can I get the seed that ExUnit uses for randomizing its test cases inside the test case?

like image 742
tkowal Avatar asked Apr 13 '16 12:04

tkowal


2 Answers

In the latest versions of Elixir, the following code will now return the seed used by ExUnit, even if one isn't specified manually:

ExUnit.configuration()[:seed]

The seed wasn't available via ExUnit.configuration in previous version unless it was manually specified. Instead, you could set the seed yourself, e.g. in your test_helpers.exs file:

ExUnit.configure seed: elem(:os.timestamp, 2)

Setting the seed like that is how ExUnit did so itself at one point.

In either case, in your test code you can do:

s = ExUnit.configuration |> Keyword.get(:seed)
:rand.seed(:exsss, {s, s, s}) #random enough for me
IO.inspect :rand.uniform(5)

Every time you run the tests you'll get a nice random value, but if you use:

$ mix test --seed <seed>

you will get the same value every time.

Note about :random

From the docs for :random:

Note

The improved rand module is to be used instead of this module.

like image 171
tkowal Avatar answered Nov 05 '22 07:11

tkowal


As of the time of this answer, the random seed is available inside of your tests by calling:

ExUnit.configuration()[:seed]

This is super nice for any tests that are dynamic by having random numbers but need to be repeatable for debugging, which was the goal of the question. If you wanted a number between 0-9, for example, you could use:

  seedable_random_number_under_10 = rem(ExUnit.configuration()[:seed], 10)

like image 3
jeffreymatthias Avatar answered Nov 05 '22 06:11

jeffreymatthias