capturing stdout during unit tests

Discussion in 'Ruby' started by Mark Slater, Aug 8, 2007.

  1. Mark Slater

    Mark Slater Guest

    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
     
    Mark Slater, Aug 8, 2007
    #1
    1. Advertising

  2. Mark Slater

    Simon Wex Guest

    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 Slater 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


    --
    Posted via http://www.ruby-forum.com/.
     
    Simon Wex, Aug 8, 2007
    #2
    1. Advertising

  3. On Aug 7, 8:59 pm, Mark Slater <> wrote:
    > I've written a script for use with Nagios (a monitoring tool) that
    > I'd like to test.


    <snip>

    > 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 :eek:utput_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
     
    Skye Shaw!@#$, Aug 8, 2007
    #3
  4. Mark Slater

    Eric Hodel Guest

    On Aug 7, 2007, at 20:59, Mark Slater 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.


    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

    --
    Poor workers blame their tools. Good workers build better tools. The
    best workers get their tools to do the work for them. -- Syndicate Wars
     
    Eric Hodel, Aug 8, 2007
    #4
  5. Mark Slater

    Mark Slater Guest

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

    Mark

    On Aug 8, 2007, at 12:08 AM, Eric Hodel wrote:

    > On Aug 7, 2007, at 20:59, Mark Slater 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.

    >
    > 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
    >
    > --
    > Poor workers blame their tools. Good workers build better tools. The
    > best workers get their tools to do the work for them. -- Syndicate
    > Wars
    >
    >
    >
     
    Mark Slater, Aug 8, 2007
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ChrisC
    Replies:
    5
    Views:
    5,764
    rochnet
    Nov 1, 2009
  2. Replies:
    8
    Views:
    910
  3. Moosebumps

    Capturing stdout incrementally

    Moosebumps, Apr 3, 2004, in forum: Python
    Replies:
    5
    Views:
    524
    David Bolen
    Apr 7, 2004
  4. Replies:
    2
    Views:
    356
  5. dayo
    Replies:
    11
    Views:
    363
    Ilya Zakharevich
    Dec 16, 2005
Loading...

Share This Page