Without further ado - some thoughts on how to use srand
in RSPEC testing. Example at the end.
Line | Input | Output |
---|---|---|
1 | srand(4) | 281462327676453734791076087004180619592 |
2 | rand(3) | 2 |
3 | rand(2) | 0 |
4 | *** | *** |
5 | srand(4) | 4 |
6 | rand(3) | 2 |
7 | rand(2) | 0 |
- line 1: We call
srand(4)
, where 4 is called a 'seed'. The function generates a number which is in fact a system time. - line 2: After calling
srand(4)
,rand(3)
is no more random - it is predetermined by a mathematical equation. Each time we callsrand(4)
and thenrand(3)
, the output will be 2. - line 3: Now we try the same operation for
rand(2)
- according to the next step of the same equation, its value is predetermined to be 0. - line 4: * * *
- lines 5-7: Now we do
srand(4)
again. It will return the value of previoussrand
- 4 and reset the random number generator. Again, the firstrand(3)
will return 2 and therand(2)
will return zero. Each time we call firstsrand(4)
and thenrand(3)
andrand(2)
we will get the same numbers: 2 and 0.
srand
may be helpful in stubbing randomness in rspec tests. Let's discuss it using the example of rock - paper - scissors.
arr = ["rock", "paper", "scissors"]
Imagine that our program has a method that choses random weapon for the computer.
def random_weapon
["rock", "paper", "scissors"].sample
end
note: Sample method is internally calling random method.
In order to stub random_weapon
function, we need to get rid of the randomness using srand
.
When we call sample, we cannot determine which of the elements of the array will be picked.
However, we can set this element by using srand
.
- First, we pick a seed - whatever we want - for example
srand(4)
. - Second, as we know that we have an array of 3 elements, we run
rand(3)
which - after first callingsrand(4)
- returns 2. - Therefore we know, that if we call
srand(4)
in our test and then callrand(3)
, we will always get the number 2. - Thanks to this we can pick the third (index 2) element in the array using sample.
class SingleGame
def computer_weapon
['scissors', 'paper', 'rock'].sample
end
end
describe SingleGame do
subject(:single_game) { described_class.new(player_1) }
let(:player_1) { double :player, name: "Justyna" }
describe "#calculate_result" do
it 'calculates the win' do
# After setting seed srand(4), rand(3) will output
# the third (index 2) element in the array, which is rock.
srand(4)
# in the following line rand(3) is called and thanks to srand(4) we know it will return 2.
allow(single_game).to receive(:computer_weapon)
expect(single_game.calculate_result(single_game.computer_weapon, "paper")).to eq "Justyna won"
end
end
end