damian
damian

Reputation: 352

Testing a whole script in Ruby

What is the best way of testing a whole script? I want to test if a script returns (prints) a correct result. So far what I have is another script that more or less does just:

# test.rb

expected = 'test'
output = `script.rb --many params`
if output != expected
  puts "Error"
end

In this example, the script I want to test is called script.rb. Cheers.

Upvotes: 0

Views: 1251

Answers (2)

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

Define Test Fixtures

What is the best way of testing a whole script? I want to test if a script returns (prints) a correct result.

You need a test fixture that includes a known input value and an expected result. In other words:

  1. Given a known input value,
  2. When you run the program
  3. Then you will receive your expected answer as output.

Note that testing an entire program this way can tell you if you got the right results from a set of inputs, but it will generally not provide insight into where the problem is. However, many forms of acceptance testing using this "black box" approach to testing, so it's certainly a reasonable approach as long as you understand the limitations.

Possible Frameworks

The list of possible testing frameworks is not infinite, but if you don't want to write your own test harness from scratch you may want to try one of the more popular ones. Some possibilities to kick-start your own research include:

There are of course plenty of others, but per your original question you will probably want to focus on ATDD or BDD testing tools, rather than unit testing, if you want to test the entire script rather than its component parts.

Upvotes: 1

tadman
tadman

Reputation: 211560

Using test-unit you end up with code like this:

class TestScript < Test::Unit::TestCase
  def test_output
    assert_equal 'test', `script --options`
  end
end

You'll probably want to use the open3 library when dealing with output from programs as that gives you more control over how that's handled. You could write your own wrapper for that as well, like assert_output_equal:

def assert_output_equal(output, command, message = nil, &block)
  Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
    assert_equal output, stdout.read, message, &block
  end
end

You can add on to that to test for the status from your process, ensuring it succeeded, and that there wasn't any output on STDERR and such.

When it comes to testing things that produce a lot of textual output (e.g. JSON data, formatted lists) I find it's best to create files in a place like test/expect and compare the file to the output rather than defining the text in the source. This makes it easy to create the files in the first place:

old_script > test/expected/old_script.default
old_script --option > test/expected/old_script.with-option

It also makes your version control diffs easier to read when something needs to be adjusted in there.

Upvotes: 3

Related Questions