* 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."