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 double
s 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
How to Solve Insecure World Writable Dir /Usr in Path,Mode 040777 Warning on Ruby
Sinatra Configuring Environments on the Fly
How to Traverse Symlinked Directories in Ruby with a "**" Glob
Ruby Timeouts and System Commands
Net::Ssh Sudo Command Hangs After Entering Password
Detect If Application Was Started as Http Server or Not (Rake Task, Rconsole etc)
Invalid Gemspec -Illformed Requirement ["#<Yaml::Syck::Defaultkey:0Xb5F9C990> 3.2.0"]
Jekyll Serve Dependency Error - Could Not Open 'Lib Curl'
Rails Active Admin CSS Conflicting with Twitter Bootstrap CSS
Combining Multiple Named Scopes with Or
How to Run Only Specific Tests in Rspec
Can You Get Db Username, Pw, Database Name in Rails