Skip to content

Instantly share code, notes, and snippets.

@Kotauror
Last active May 14, 2019 09:09
Show Gist options
  • Save Kotauror/8f4a9913c53dd479df91909f306e6731 to your computer and use it in GitHub Desktop.
Save Kotauror/8f4a9913c53dd479df91909f306e6731 to your computer and use it in GitHub Desktop.
srand in RSPEC stubbing.

srand in RSPEC stubbing.

Without further ado - some thoughts on how to use srand in RSPEC testing. Example at the end.

How does the srand work line by line.

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 call srand(4) and then rand(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 previous srand - 4 and reset the random number generator. Again, the first rand(3) will return 2 and the rand(2) will return zero. Each time we call first srand(4) and then rand(3) and rand(2) we will get the same numbers: 2 and 0.

How to use srand in rspec mocking.

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 calling srand(4) - returns 2.
  • Therefore we know, that if we call srand(4) in our test and then call rand(3), we will always get the number 2.
  • Thanks to this we can pick the third (index 2) element in the array using sample.

Example

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment