11

My Ruby program reads lines from stdin and uses puts to print to stdout (the terminal). Can I use RSpec to test the reads and writes? Can I inject a string to my program like it was written in stdin and at the same time check the output?

line = STDIN.read.chomp.split

Also, I have the reads and writes in a loop, until line[0] is "quit". Can I test while the loop is running or should I call subject.read_in and subject.write_out?

Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
pvinis
  • 4,059
  • 5
  • 39
  • 59

2 Answers2

16

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.

Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
Jonathan
  • 3,203
  • 2
  • 23
  • 25
  • 1
    It's `STDOUT.should_receive(:print)` actually. – yawn Sep 27 '11 at 12:27
  • how do you even know to use :print or :read....where does this exist in the "how to use RSpec" documentation? everywhere I turn I see expectations I've never heard of (I own the RSpec book) I can not find a definitive text on this subject. – thefonso Aug 31 '12 at 20:49
  • @thefonso `print` and `read` are methods on STDOUT and STDIN respectively. They are nothing to do with RSpec. If you don't understand this I would *strongly* encourage you to spend some time studying Ruby separately from RSpec or any other library. – Jonathan Sep 03 '12 at 14:22
  • 1
    There's a good post on what's wrong with having expectations like these here: http://ngauthier.com/2010/12/everything-that-is-wrong-with-mocking.html – Louis Sayers Sep 20 '12 at 08:03
2

RSpec 3.0+

With RSpec 3.0, there is output matcher for this purpose:

expect { my_method }.to output("my message").to_stdout
expect { my_method }.to output("my error").to_stderr
Daniel Garcia
  • 1,382
  • 1
  • 10
  • 9