0

I am fairly new to rspec and want to write test in rspec for getting input from command line in Ruby. How do I go about it? Also, explain the test. Thanks

2
  • Do you want to test the given standard input or command line arguments e.g. ruby foo.rb --argument1 --argument2? Can you give an example of what you are trying to test? Commented Sep 18, 2012 at 14:06
  • a = gets kind of requests.I implemented this @life.stub(:gets) { "5" } (next line) @life.input.should == 5 but i don't know wether this is right practice. Commented Sep 18, 2012 at 14:09

2 Answers 2

2

By using mocks:

STDIN.should_receive(:read).and_return("your string")

Also I like the approach which is described here. I think that the last one is more suitable for your case.

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

Comments

2

The general approach is to make such kind of objects swappable. In your case, gets is implicitly called on $stdin. So you can make an optional argument called "input" that defaults to $stdin and call gets on it.

Here is an simple example of Calculator that takes some input and gives the result back.

class Calculator
  def initialize input = $stdin
    @input = input
  end

  def process
    eval @input.gets
  end
end

Now you can run puts Calculator.new.process, type 1 + 2 and you will see 3.

You won't need any special tools for testing this because you can easily pass an IO object and write to it right in your tests. IO.pipe is a good option for this:

describe "Calculator" do
  before do
    reader, @writer = IO.pipe
    @calc = Calculator.new(reader)
  end

  it "can sum up two numbers" do
    @writer.puts "1 + 2"
    result = @calc.process
    result.should eq(3)
  end
end

You can also use StringIO instead which is not a real IO and does not require a UNIX-like environment. Although you will need to rewind the stream each time you write.

require "stringio"

describe "Calculator" do
  before do
    @input = StringIO.new
    @calc = Calculator.new(@input)
  end

  it "can sum up two numbers" do
    @input.puts "1 + 2"
    @input.rewind
    result = @calc.process
    result.should eq(3)
  end
end

The upside of this approach versus stubbing are less brittle tests and a better design. The tests are less brittle because if you decide to change the implementation and use getc instead of gets (read characters one by one) for example you won't need to change the tests. And the design is better because now you can easily give commands from a different source such as a file Calculator.new(File.open("calculated_list.txt")). Or a fake IO which you can use in your tests!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.