Forum: Ruby redirecting stdout to a String

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
52a177e9dbd3e614825aabc4e45f8cd6?d=identicon&s=25 Mark Volkmann (Guest)
on 2006-03-24 14:50
(Received via mailing list)
I wrote a unit test for a method that writes to stdout. I got it to
work, but I'm not sure my approach was the best. Is there a more
recommended way to do this?

    # Create a String with a singleton write method
    # that allows it to take the place of stdout.
    actual = '''
    def actual.write(data); self << data; end
    old_stdout, $stdout = $stdout, actual

    # Invoke method to test that writes to stdout.

    $stdout = old_stdout # restore stdout
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-24 14:57
(Received via mailing list)
On Mar 24, 2006, at 7:50 AM, Mark Volkmann wrote:

> I wrote a unit test for a method that writes to stdout. I got it to
> work, but I'm not sure my approach was the best. Is there a more
> recommended way to do this?
>
>     # Create a String with a singleton write method
>     # that allows it to take the place of stdout.
>     actual = '''
>     def actual.write(data); self << data; end

See the standard library, StringIO.

James Edward Gray II
52a177e9dbd3e614825aabc4e45f8cd6?d=identicon&s=25 Mark Volkmann (Guest)
on 2006-03-24 15:12
(Received via mailing list)
On 3/24/06, James Edward Gray II <james@grayproductions.net> wrote:
>
> See the standard library, StringIO.

Thanks!  I have that working, but it's not clear to me how that is
better. In fact, it seems to take more code to do it that way. I now
have this.

  require 'stringio'

  sio = StringIO.new
  old_stdout, $stdout = $stdout, sio
  # Invoke method to test that writes to stdout.
  $stdout = old_stdout # restore stdout
  actual = sio.string

Am I overcomplicating this?
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2006-03-24 16:32
(Received via mailing list)
On 3/24/06, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:
> > >     actual = '''
>   sio = StringIO.new
>
>
I made a benchmark of both solutions, but I was surprised how small the
difference was.
StringIO is faster, as I expected. See below for results.
Apart from that I feel that stringio will have adavantages for giving
you a
complete API.
But for a quick solution the singleton method seems elegant and I like
it a
lot, after all
you do not require( which was not benchmarked!!!) 'stringio' and run a
core
script.

But for reusable code I'll defenitely go for stringio.

Cheers
Robert

---------------------------------- 8<
-------------------------------------


 cat stringio.rb;ruby stringio.rb
#!/usr/bin/env ruby
   # Create a String with a singleton write method
   # that allows it to take the place of stdout.
 require 'benchmark'
 require 'stringio'

 n = 500000
 r1 = r2 = nil
 Benchmark.bm do
        |bm|
        bm.report "single string" do
            actual = ''

            def actual.write(data); self << data.to_s; end
            old_stdout, $stdout = $stdout, actual
            n.times{ |i| $stdout.write i }
            $stdout = old_stdout
            r1= actual
        end # do

        bm.report "stringio     " do
                 sio = StringIO.new
                 old_stdout, $stdout = $stdout, sio
                 n.times{ |i| $stdout.write i}
                 # Invoke method to test that writes to stdout.
                 $stdout = old_stdout # restore stdout
                 r2 = sio.string
        end # do
 end # do

 raise Exception unless r1 == r2


      user     system      total        real
single string  1.460000   0.000000   1.460000 (  1.823057)
stringio       1.320000   0.010000   1.330000 (  1.828039)


--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-24 17:08
(Received via mailing list)
On Mar 24, 2006, at 8:12 AM, Mark Volkmann wrote:

>>>     def actual.write(data); self << data; end
>>
>> See the standard library, StringIO.
>
> Thanks!  I have that working, but it's not clear to me how that is
> better. In fact, it seems to take more code to do it that way.

You originally asked:

>>> Is there a more recommended way to do this?

I was just trying to answer that question.

I prefer the StringIO method because it is a full mock API, as Robert
Dober said.  However, if you know you will only need the one method
(now and forever?!) there is probably little difference.

James Edward Gray II
This topic is locked and can not be replied to.