Testing Stdin in Ruby

Testing STDIN in Ruby

You can simply stub STDIN:

it "takes user's name and returns it" do
output = capture_standard_output { game.ask_for_name }
expect(output).to eq "What shall I call you today?"
allow(STDIN).to receive(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end

Actually, you can do the same with STDOUT, without needing to change $stdout:

it "takes user's name and returns it" do
expect(STDOUT).to receive(:puts).with("What shall I call you today?")
allow(STDIN).to receive(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end

how to test STDIN with RSpec

Because move_computer returns the input, I think you meant to say:

player.move_computer("O").should == "\n"

I would write the full spec like this:

describe Player do
describe "#move_computer" do
it "returns a line from stdin" do
subject.stub!(:gets) {"penguin banana limousine"}
STDOUT.should_receive(:puts).with("computer move")
subject.move_computer("O").should == "penguin banana limousine"
end
end
end

How to test stdin for a CLI using rspec

I ended up finding a solution that I think fairly closely mirrors the code for executing instructions from a file. I overcame the main hurdle by finally realizing that I could write cli.stub(:gets).and_return and pass it in the array of commands I wanted to execute (as parameters thanks to the splat * operator), and then pass it the "EXIT" command to finish. So simple, yet so elusive. Many thanks go to this StackOverflow question and answer for pushing me over the line.

Here is the code:

describe "executing instructions from the command line" do
let(:output) { capture(:stdout) { cli.execute } }

context "with valid commands" do
valid_test_data.each do |data|
let(:expected_output) { data[:output] }
let(:commands) { StringIO.new(data[:input]).map { |a| a.strip } }

it "should process the commands and output the results" do
cli.stub(:gets).and_return(*commands, "EXIT")
output.should include(expected_output)
end
end
end
# ...
end

Can I use RSpec to mock stdin/stdout to test console reads & writes?

You can use mocks and have the method called more than once by listing multiple values in the and_return() method. These will be returned, one on each call, in the order given.

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

STDIN.should_receive(:read).and_return("value1", "value2", "value3")

You can do similar things with STDOUT:

STDOUT.should_receive(:puts).with("string")

See the RSpec mocking documentation for more information.

Testing ruby with rspec for file name and STDIN with while gets

How about this idea?

[EDITED]

For the main script…

require 'processor'
sources = ARGV.map{ |fname| File.open(fname) }
sources = [$stdin] if sources.empty?
Processor.new(sources).process

…and for processor.rb…

Class Processor
attr_reader :sources
attr_accessor :card_hash

def initialize(sources)
@sources = sources
@card_hash = Hash.new
end

def process
sources.each do |source|
source.each_line.do |line|
...

Then, for testing purposes, you can pass an array of one or more stub objects for the sources. The stub objects could be something like RSpec doubles or an instances of StringIO. See http://apidock.com/ruby/StringIO .

How can you check for STDIN input in a Ruby script?

This is something that's done in Linux a lot:

#!/usr/bin/env ruby

str = (STDIN.tty?) ? 'not reading from stdin' : $stdin.read
puts str

>> $ ruby test.rb
>> not reading from stdin
>> $ echo "reading from stdin" | ruby test.rb
>> reading from stdin


Related Topics



Leave a reply



Submit