# Capturing stdout during unit tests

**URL:** <https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520>\
**Category:** Ruby\
**Created:** [August 8, 2007, 6:39am UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520 "2007-08-08T06:39:46Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [August 8, 2007, 6:39am UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/1 "2007-08-08T06:39:46Z")

</div>

I’ve written a script for use with Nagios (a monitoring tool) that  
I’d like to test. The requirements for the script is that it output a  
single line of text to STDOUT and then exit with a status code (0 -  
3). My script is designed to monitor a few different services… each  
invocation includes a required command line argument specifying the  
service to monitor in the current invocation. To do that, I created a  
class for each type of service monitor.

I’m now writing unit tests for my script, and I’d like to check that  
the output written to STDOUT by each service monitor class is  
correct. But I’m new to Ruby and I’m not sure how to do that. In  
other languages, I’d simply redefine STDOUT as a stream that goes to  
a large in-memory buffer, but I haven’t seen anything that suggests  
that is possible in Ruby. The best I’ve come up with so far is  
creating a temporary file and calling $stdout.reopen() with the path  
to that temporary file. However, I’d much rather do this in memory  
because then I never have to worry about what file system and  
permissions the user executing the unit test has.

Thanks,

Mark

---

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [August 8, 2007, 7:17am UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/2 "2007-08-08T07:17:01Z")

</div>

One option is to write your test to execute your script on the command  
line. I’m pretty sure this is the piece you’re missing:

# asign the shell output of the ls command to a variable

ls\_output = `ls`

# Do something semi-useful with it.

items = ls\_output.split  
puts “There are #{items.size} objects in the directory.”

-Simon

Mark S. wrote:

> I’ve written a script for use with Nagios (a monitoring tool) that  
> I’d like to test. The requirements for the script is that it output a  
> single line of text to STDOUT and then exit with a status code (0 -  
> 3). My script is designed to monitor a few different services… each  
> invocation includes a required command line argument specifying the  
> service to monitor in the current invocation. To do that, I created a  
> class for each type of service monitor.
> 
> I’m now writing unit tests for my script, and I’d like to check that  
> the output written to STDOUT by each service monitor class is  
> correct. But I’m new to Ruby and I’m not sure how to do that. In  
> other languages, I’d simply redefine STDOUT as a stream that goes to  
> a large in-memory buffer, but I haven’t seen anything that suggests  
> that is possible in Ruby. The best I’ve come up with so far is  
> creating a temporary file and calling $stdout.reopen() with the path  
> to that temporary file. However, I’d much rather do this in memory  
> because then I never have to worry about what file system and  
> permissions the user executing the unit test has.
> 
> Thanks,
> 
> Mark

---

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [August 8, 2007, 9:05am UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/3 "2007-08-08T09:05:57Z")

</div>

On Aug 7, 8:59 pm, Mark S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’ve written a script for use with Nagios (a monitoring tool) that  
> I’d like to test.

> I’m now writing unit tests for my script, and I’d like to check that  
> the output written to STDOUT by each service monitor class is  
> correct. But I’m new to Ruby and I’m not sure how to do that. In  
> other languages, I’d simply redefine STDOUT as a stream that goes to  
> a large in-memory buffer,

What language is this in?

> but I haven’t seen anything that suggests that is possible in Ruby.  
> At any rate, Ruby does have similar functionality. An example:

require ‘stringio’  
class Bs  
attr :output\_stream,true

def do\_some\_output(data)  
output\_stream.puts(data)  
end  
end

bs=Bs.new  
bs.output\_stream=$stdout  
bs.do\_some\_output(“this is to stdout”)

expect=“grrrrrrrr”  
result=String.new

bs.output\_stream=StringIO.new(result,“w+”)  
bs.do\_some\_output(“Waka waka waka!”)  
bs.output\_stream.close

puts "result= " + result  
puts "expect= " + expect

[sshaw@localhost sshaw]# ruby bs.rb  
this is to stdout  
result= Waka waka waka!  
expect= grrrrrrrr

---

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [August 8, 2007, 11:09pm UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/4 "2007-08-08T23:09:26Z")

</div>

Awesome! Thank you. That’s exactly the functionality I was looking for.

Mark

---

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [August 8, 2007, 9:09am UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/5 "2007-08-08T09:09:58Z")

</div>

On Aug 7, 2007, at 20:59, Mark S. wrote:

> correct. But I’m new to Ruby and I’m not sure how to do that. In  
> other languages, I’d simply redefine STDOUT as a stream that goes  
> to a large in-memory buffer, but I haven’t seen anything that  
> suggests that is possible in Ruby. The best I’ve come up with so  
> far is creating a temporary file and calling $stdout.reopen() with  
> the path to that temporary file. However, I’d much rather do this  
> in memory because then I never have to worry about what file system  
> and permissions the user executing the unit test has.

Install the ZenTest gem, then:

require ‘test/zentest\_assertions’

class TestBlah \< Test::Unit::TestCase

def test\_my\_stuff  
out, err = util\_capture do the\_thing end  
assert\_equal “…”, out.string  
assert\_equal “…”, err.string  
end  
end

---

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [September 25, 2007, 11:09pm UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/6 "2007-09-25T23:09:17Z")

</div>

On 8/08/2007, at 3:59 PM, Mark S. wrote:

> correct. But I’m new to Ruby and I’m not sure how to do that. In  
> other languages, I’d simply redefine STDOUT as a stream that goes  
> to a large in-memory buffer, but I haven’t seen anything that  
> suggests that is possible in Ruby. The best I’ve come up with so  
> far is creating a temporary file and calling $stdout.reopen() with  
> the path to that temporary file. However, I’d much rather do this  
> in memory because then I never have to worry about what file system  
> and permissions the user executing the unit test has.
> 
> Thanks,

Try this:

require ‘stringio’

$stdout = StringIO.new

(This will break in IRB w/ Readline)

StringIO has all the IO methods, but acts on a string, not a file. So  
you should be able to do what you want.

Cheers

Phil

---

<div class="post-metadata">

**Author:** ![mslagell](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e274bd/32.png) [@mslagell](https://www.ruby-forum.com/u/mslagell)\
**Post date:** [August 31, 2008, 8:44am UTC](https://www.ruby-forum.com/t/capturing-stdout-during-unit-tests/111520/7 "2008-08-31T08:44:12Z")

</div>

> Install the ZenTest gem, then:
> 
> require ‘test/zentest\_assertions’
> 
> class TestBlah \< Test::Unit::TestCase
> 
> def test\_my\_stuff  
> out, err = util\_capture do the\_thing end  
> assert\_equal “…”, out.string  
> assert\_equal “…”, err.string  
> end  
> end

if you’re not using test/unit:

require ‘test/zentest\_assertions’  
include Test::Unit::Assertions
