Home > OS >  Trying to test my randomiser in rspec by passing specific numbers to it
Trying to test my randomiser in rspec by passing specific numbers to it

Time:02-27

I am currently trying to create a test for the below code. I wrote the test first and then wrote the code and realised my test is not doing what I want it to do.

class Weather

  def initialize
    @weather = 'sunny'
  end

  def weather_randomiser
    case rand(1..10)
    when 1..8 then @weather = 'sunny'
    when 9..10 then @weather = 'stormy'
    end
  end

  def stormy?
    weather_randomiser
    @weather == 'stormy'
  end
end

My test is as follows:

require 'weather.rb'

describe Weather do
  it 'randomises weather and sets the weather to the randomised result' do
    weather = Weather.new
    allow(weather).to receive(:weather_randomiser).and_return(9)
    expect(weather).to be_stormy
    allow(weather).to receive(:weather_randomiser).and_return(2)
    expect(weather).to_not be_stormy
  end
end

Can you please explain how I go about testing the weather_randomiser and stormy? methods similar to this/ is it possible with my code.

Further could you explain how you got to where you did as I would like to understand not just have an answer.

Thank you very much in advance :)

CodePudding user response:

I believe you can use the following snippet. Here you want to stub the rand function itself. I really don't recommend that. I would recommend if you have your class that may be called Randomizer and it contains the random class. Stubbing classes like Object is not good at all.

#!/usr/bin/env ruby
require_relative '../weather.rb'

RSpec.describe Weather do
  it 'randomises weather return stormy' do
    allow_any_instance_of(Object).to receive(:rand).and_return(9)
    weather = Weather.new
    expect(weather).to be_stormy
  end

  it 'randomises weather return sunny' do
    allow_any_instance_of(Object).to receive(:rand).and_return(4)
    weather = Weather.new
    expect(weather).to_not be_stormy
  end
end

CodePudding user response:

Your weather_randomiser does too many things:

  1. It generates a random number
  2. It maps a random number to a string value
  3. It updates an instance variable

To make things more testable, you could split those out, e.g.:

def weather_randomiser
  rand(1..10)
end

def set_weather(value)
  @weather = case value
    when 1..8 then @weather = 'sunny'
    when 9..10 then @weather = 'stormy'
  end
end

def stormy?
  set_weather weather_randomiser
  @weather == 'stormy'
end

It does introduce an awkward coupling between the randomiser and setter; changing the former requires looking at the latter ... ymmv

  • Related