Reputation: 6862
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
Upvotes: 0
Views: 1387
Reputation: 20639
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!
Upvotes: 2