Testing Standard Input and Output in Ruby with the Minitest Framework

Gil Roman
Gil Roman
Sep 5, 2018 · 4 min read

This is a guide showing a simple way to test functions that utilize standard input and standard output methods in Ruby using the Minitest framework.

Minitest

Minitest is a testing framework included with Ruby. In our test file we will first use Ruby’s require method with the argument ‘minitest/autorun’ in order to be able to run our tests.

require 'minitest/autorun'

If the code we are testing is on a separate file from the test file, we will also write in our test file the require_relative method with the relative path to the file containing the code we are testing as an argument. In this example, our project directory has a ‘src’ folder for the source code files and a ‘tests’ folder for the test files.

The test file is named : ‘test_command_line_interface.rb’ and the source file is named ‘command_line_interface.rb’. Our test file starts out like this.

require 'minitest/autorun'
require '../src/command_line_interface.rb'

The StringIO Class

The ruby StringIO class is basically a string object with additional IO methods like: gets, puts, write, and print. We will use an instance of the StringIO class to simulate Input and Output in our tests.

Testing Standard Input

Our first test will create a variable named input which points to an instance of the StringIO class. We initialize it with the string “testing_123”. This simulates a user having typed in “testing_123” in the computer’s terminal.

We also create a variable “cli” which points to an instance of our CommandLineInterface class. Our class’ initialize method will accept arguments for the objects that we want to use for Standard Input and Standard Output. In our input test we want to pass our instance of the StringIO object when we initialize it.

The CommandLineInterface class also has a readInput method. We send a message to that method and store its return value in a variable called value.

Finally, we assert that the string “testing_123” is equal to value.

describe CommandLineInterface do
it 'reads input' do
input = StringIO.new("testing_123")
cli = CommandLineInterface.new(input, nil)
value = cli.readInput

assert_equal "testing_123", value
end
end

Testing Standard Output

Our second test will create a variable named output which points to an instance of the StringIO class. We won’t provide a string when initializing the StringIO class because we want the function that we are testing in our CommandLineInterface class to add the value to it.

We then create a variable “cli” which points to an instance of our CommandLineInterface class. When we instantiate the CommandLineInterface class we want to pass nil as a first argument because the function being tested won’t be using standard input, and the “output” variable as the second argument.

The CommandLineInterface class also has a printOut method. We send a message to that method with the string “testing_123” as an argument.

Finally we make an assertion comparing the string “testing_123” against the value of the string property in our output object. This confirms that the printOut method worked in our CommandLineInterface class.

describe CommandLineInterface do
it 'prints to stdout' do
output = StringIO.new
cli = CommandLineInterface.new(nil, output)

cli.printOut("testing_123")
assert_equal "testing_123", output.string
end
end

The Complete Test Specification

require 'minitest/autorun'
require_relative '../src/command_line_interface.rb'
describe CommandLineInterface do
it 'prints to stdout' do
output = StringIO.new
cli = CommandLineInterface.new(nil, output)

cli.printOut("testing_123")
assert_equal "testing_123", output.string
end
it 'reads input' do
input = StringIO.new("testing_123")
cli = CommandLineInterface.new(input, nil)
value = cli.readInput

assert_equal "testing_123", value
end
end

Our CommandLineInterface Class

The CommandLineInterface class will implement an initialize method with default arguments for input and output pointing to $stdin and $stdout respectively. $stdin and $stdout are global variables in Ruby. These variables point to Ruby constants STDIN and STDOUT which in turn point to objects of the IO class. These IO class objects are wrappers around input and output streams.

In our tests when we initialize the CommandLineInterface class we pass in as arguments instances of the StringIO class so that they are used instead of the default $stdin and $stdout arguments.

In our folder structure, this class is in the ‘command_line_interface.rb’ file inside the ‘src’ folder.

class CommandLineInterface 
def initialize(input = $stdin, output = $stdout)
@input = input
@output = output
end
def printOut(string)
@output.print(string)
end
def readInput
@input.gets.chomp
end
end

Running The Tests

To run these tests in our terminal we want to navigate to our tests folder and run the command ‘ruby test_command_line_interface.rb’.

In summary, Ruby provides a StringIO class which implements standard input and output methods that is very helpful to simulate user input and system output inside our tests.

Gil Roman

Written by

Gil Roman

Software engineer exploring the boundary between art and technology.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade