* Adriano R. Ferreira <[EMAIL PROTECTED]> [2004-02-09 01:56]: > While writing tests for some of my code, I was faced with the issue > of capturing what the code sends to STDOUT and STDERR. As I have not > found a module to make it easy, I wrote a trivial code to do it. It > is used like this: > > use Test::More tests => 2; > use Seize qw(seize release); > > my ($out, $err); > > seize \$out, \$err; # from here on, STDOUT and STDERR are seized > > print "1\n"; > warn "2\n"; > print "3\n"; > eval { die "4\n"; } > > release; # here STDOUT and STDERR are released > > is($out, "1\n3\n"); > is($err, "2\n3\n"); > > My doubt is if this deserves a module: maybe it would be better > to use idioms commonly employed to this kind of task. Maybe > there is some module I am overlooking that already does that.
For Perl 5.8 (and 5.6 with IO::String? I think it works there) it's trivial: use Test::More tests => 2; use Carp; sub string_fh { open my $fh, '>', $_[0] or croak "Couldn't open scalar as filehandle: $!\n"; return $fh; } my ($out, err); { local STDOUT, STDERR; *STDOUT = string_fh \$out; *STDERR = string_fh \$err; print "1\n"; warn "2\n"; print "3\n"; eval { die "4\n"; } } is($out, "1\n3\n"); is($err, "2\n3\n"); I believe this is a lot more robust than a tie() solution as well. But it isn't really modularizable due to the local() and there's not much anyway to stick in a module. Another approach I only have the time to sketch here: use Test::More tests => 2; use Carp; sub redir_fh { my ($fh, $mode, $file); my $saved_fh; # dup $fh in here open $fh, $mode, $file # not sure this msg makes sense.. or croak "Couldn't dup $fh to $file: $!\n"; return bless [ $fh, $saved_fh ], 'RestoreHandle'; } sub RestoreHandle::DESTROY { # use $self to dup the original FH back into the used one } my ($out, err); { my $s_out = redir_fh \*STDOUT, '>', \$out; my $s_err = redir_fh \*STDERR, '>', \$err; print "1\n"; warn "2\n"; print "3\n"; eval { die "4\n"; } } # $s_* went out of scope here.. is($out, "1\n3\n"); is($err, "2\n3\n"); which uses lexical variables to implement dynamic scoping. :) -- Regards, Aristotle "If you can't laugh at yourself, you don't take life seriously enough."