Testing with STDIN and STDOUT

Recently, I started working on http://codeforces.com/ problem set. They uses STDIN (standard input) and STDOUT (standard output) for the program input/output.

After researching on a way to write test codes against STDIN/STDOUT, I managed to reach to the following code. It’s a little tricky, but I find it relatively compact and useful.

spec_helper.rb

require "rspec"

def test(input, output)
  capture(:stdout) {
    fake_stdin(input){ yield }
  }.should == output
end

def fake_stdin(*args)
  begin
    $stdin = StringIO.new
    $stdin.puts(args.shift) until args.empty?
    $stdin.rewind
    yield
  ensure
    $stdin = STDIN
  end
end

def capture(stream)
  begin
    stream = stream.to_s
    eval "$#{stream} = StringIO.new"
    yield
    result = eval("$#{stream}").string
  ensure
    eval("$#{stream} = #{stream.upcase}")
  end

  result
end

sample.rb

def run
  a, b = $stdin.readline.split.map { |x| x.to_i }
  puts a + b
end

run if $0 == __FILE__

sample_spec.rb

require 'rspec'
require 'spec_helper'
require 'sample'

describe do
  it "adds two values" do
    test("1 2\n", "3\n") { run }
  end
end
Advertisements

Posted on January 20, 2013, in Ruby. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: