0

I probably have done some silly mistake but by running rake shows this

rake

Due to infinite loop it runs infinitely until i stopped it.

The folder structure follows :

folder

calculator.rb

class Calculator

    attr_accessor :result

    def initialize
        @result = 0.0
    end

    def add(param)
        @result += param
    end

    def subtract(param)
        @result -= param
    end

    def multiply(param)
        @result *= param
    end

    def divide(param)
        @result /= param
    end

    def cancel
        @result = 0.0
    end
end

class CommandProcessor
    attr_accessor :input
    attr_accessor :operation
    attr_accessor :calculator

    def parser
        calculator = Calculator.new
        while true
            input = gets.to_s.chomp
            operation = input.split(' ')[0]
            param = input.split(' ')[1]
            if operation.eql? 'exit'
                exit
            elsif operation.eql? 'add'
                calculator.add(param.to_f)
                puts calculator.result
            elsif operation.eql? 'subtract'
                calculator.subtract(param.to_f)
                puts calculator.result
            elsif operation.eql? 'multiply'
                calculator.multiply(param.to_f)
                puts calculator.result
            elsif operation.eql? 'divide'
                calculator.divide(param.to_f)
                puts calculator.result
            elsif operation.eql? 'cancel'
                calculator.cancel
                puts calculator.result
            else
                puts "invalid op"
            end
        end
    end
end

command = CommandProcessor.new
command.parser

calculator_spec.rb

require 'spec_helper'
require "calculator.rb"

describe "CommandProcessor" do
    it "will exit on input exit" do
        @cmd = CommandProcessor.new
        @cmd.stub!(:gets).and_return("add 3\n")
        @cmd.parser
        expect(@cmd.calculator.result).to eq 3
    end
end

describe "Calculator" do
    it "will add a number" do
        calculator = Calculator.new
        expect(calculator.add 2).to eq 2.0
        expect(calculator.add 2.0).to eq 4.0
    end

    it "will subtract a number" do
        calculator = Calculator.new
        expect(calculator.subtract 2).to eq -2.0
        expect(calculator.subtract 2.0).to eq -4.0
    end

    it "will multiply a number" do
        calculator = Calculator.new
        expect(calculator.multiply 2).to eq 0.0
        expect(calculator.multiply 2.0).to eq 0.0
    end

    it "will divide a number" do
        calculator = Calculator.new
        expect(calculator.divide 2).to eq 0.0
        expect(calculator.divide 2.0).to eq 0.0
    end

    it "will make result zero on cancel" do
        calculator = Calculator.new
        calculator.cancel
        expect(calculator.result).to eq 0.0
    end
end

Have i structured the code wrongly or my test are wrong? The code works fine but not the test cases.

1 Answer 1

2

Well the prime culprit for the infinite loop, is the one you've introduced yourself, in CommandProcessor#parser.

I believe the problem is that you are stubbing gets on your object, but actually, it is defined on Kernel, so if you are going to stub it anywhere, that's where. This means that gets is probably returning some sort of nonsense that your parser does not understand, which leads to the infinite loop of invalid op that you see. It would probably be useful to print what the invalid op was in that case (i.e. change the puts "invalid op" to puts "invalid op: #{operation}".)

It is worth noting that even if your stub had worked, and you kept getting add 3 instead of garbage data, your programming would still loop forever, because the parser never receives an exit, which it needs to break from the loop.

In my opinion, this issue is indicative of another problem: You are trying to test two things in one go: The parser, and the IO. I would suggest altering your interface so that your CommandProcessor.parse took a string, parses it, and returns the result from the internal Calculator instance. Then it becomes almost trivial to test, which is what we want (nobody wants to think too hard).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.