Shan_Boy
Shan_Boy

Reputation: 19

Rspec for checking of a number

I am a ruby newbie, I have managed to pull out the code for ruby but writing rspecs for them seems problematic. It's hard to understand the way to write rspecs even after reading few tutorials. Someone please help me to write for an input method then I would try to refactor it for the rest.

RB file:

module RubyOperations
  class Operations
    def input(num)
      RubyOperations.log('Enter a number:[Between 1 to 10]',:BOTH)
      num = Integer(gets.chomp)
      raise StandardError if num <= 0 || num > 10
      return num
    rescue StandardError, ArgumentError => e
      RubyOperations.log(e,:ERROR)
    end
  end
end

RSPEC:

describe 'RubyOperations' do
  describe 'Operations' do
    describe '.input' do
      context 'when number is provided' do
        it 'returns the number provided' do
          expect(RubyOperations.input(num)).to eq(Integer)
        end
      end
    end
  end
end

Upvotes: 0

Views: 5658

Answers (2)

teckden
teckden

Reputation: 337

There are few issues with code that you have shared:

1) In the Operations class, the method input receives an argument which is not used anywhere because of this line: num = Integer(gets.chomp). Basically gets is the method that waits for user input, and the assignment num = ... overrides the value of argument (num) that is passed into the method, hence it is pointless to pass num argument into the method.

2) In your spec sample you call input method on RubyOperations module, while the input lives in class Operations under namespace RubyOperations. Also method input is not a class method but instance method. So proper method call would be: RubyOperations::Operations.new.input(5)

3) To run a spec for input method you would need to stub user input. RSpec-mocks gem can help you with that - https://github.com/rspec/rspec-mocks. It has allow stub method: allow(object).to receive(:gets) { "5" }

The whole sample will be:

it 'returns the number provided' do
  # instantiate object that we will test
  subject = RubyOperations::Operations.new

  # we stub method 'gets' and whenever it is called we return string "5"
  allow(subject).to receive(:gets) { "5" } 

  # we call method input with argument 1, the argument 1 is pointless as described in point 1) and can be omitted
  expect(subject.input(1)).to eq(5)
end

Upvotes: 0

Sumanth Madishetty
Sumanth Madishetty

Reputation: 3605

You can check the class of the output of the method to equal integer

require 'ruby_final_operations'
  describe 'RubyOperations' do
    describe 'Operations' do
      describe '.input' do
        context 'when number is provided' do
          it 'returns the number provided' do
            expect(RubyOperations.input(num).class).to eq(Integer)
            (or)
            expect(RubyOperations.input(num)).to be_a_kind_of(Integer) 
          end
         end
        end
       end
      end

And whenever you write rspec keep in mind

If the method for which you are writing rspec deals with manipulations in your db then check if db is manipulated or not

Or if you are writing rspec for any methods which returns an object then procced like this

if a method is defined like

def square_of_a_number(num)
 num*num
end

Then write rspec like this

it 'returns square of a number' do
  expect(square_of_a_number(2).to eq(4)   
end

For any methods that you know the output of a method will be that then hardcode the input or user Faker gem for input of the method expect the expected result of that method

Upvotes: 1

Related Questions