A Pattern For Using Standard In And Out In Your Ruby Code
If you think about it, programming is really about taking some input from a user, and displaying some output back to them. When we’re down at the command line, this usually means reading from the standard input and writing to the standard output.
In ruby, you’ll see code that interacts with standard in and standard out like so:
Sadly though, when it comes testing, usually the input/output stuff is glossed over. Why though?
- Extraneous output is often generated during testing
- It’s hard to specify what stdin returns and verify what stdout displays back to the user
“Don’t let not having the tools be your trepidation… I will never make a criticism if I don’t have a resolution.” - Joel Bauer
Allow me, then, to outline a pattern for using standard input and standard output in your Ruby code in a way that’s testable.
First off, don’t use just ‘puts’ and ‘gets’ by themselves. If you check out the rdoc for
Kernel, you’ll see that these are just shorthand for
$stdin.gets. So we’ll change our code to be more like:
Tests still pass, right? Alright, next we’re going to create some
MyApp for the input/output. By default, we’ll make them point at
$stdout so they’ll work as expected by default, but during your tests… well, we’ll get to that in a minute.
Now we’re setup to test this proper like.
But first, we need a little background on
$stdout. If you pop up an
irb session and enter
$stdout.class, you’ll see its is IO. I’m not going to go into much more detail, but suffice to say, StringIO exists as a way to make an
IO that you can muck around with more easily for testing. To provide input to
StringIO, you pass a string to its constructor. To check the output to
StringIO, use the
string method to return it. Knowing that, we can test it now:
And there we go: ruby code using stdin and stdout that we’re able to test easily.