Alpha Hydrae

Coding on the edge of the web...

Capturing Output in Pure Ruby

Rails has its own capture method but I’ve often needed to capture the output in a Ruby script, mainly for unit testing purposes. It is pretty easy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require 'stringio'

# redirect output to StringIO objects
stdout, stderr = StringIO.new, StringIO.new
$stdout, $stderr = stdout, stderr

# output is captured
puts 'foo'
warn 'bar'

# restore normal output
$stdout, $stderr = STDOUT, STDERR

stdout.string.match /foo/   #=> true
stderr.string.match /bar/   #=> true

I like to wrap this to make it a bit more practical:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
require 'stringio'
require 'ostruct'

class Capture

  def self.capture &block

    # redirect output to StringIO objects
    stdout, stderr = StringIO.new, StringIO.new
    $stdout, $stderr = stdout, stderr

    result = block.call

    # restore normal output
    $stdout, $stderr = STDOUT, STDERR

    OpenStruct.new result: result, stdout: stdout.string, stderr: stderr.string
  end
end

c = Capture.capture do
  puts 'foo'
  warn 'bar'
end

c.stdout.match 'foo'   #=> true
c.stderr.match 'bar'   #=> true

Meta

  • Ruby: 1.9.3 & 2.0.0

Comments