Test::More::STDIO ?

heusserm on 2003-08-19T15:39:14

So, you have some functions that print some things to STDIO - perhaps CGI Functions.

But you are writing tests, and you see a buncha gobbly-good HTML amoung your "oks". What's worse, you want to test that HTML. (For example, when you search on "Stuff", you want to make sure the table that is returned has rows, so you have a regex to check for that.)

This morning, Jeff Klein proposed the following code snippet to me to get HTML back as a string:

sub capture (&) {
use IO::String;
my $strfh = IO::String->new;
my $oldfh = select($strfh);
shift->();
select($oldfh);
return ${ $strfh->string_ref };
}


Here's it in use:
my $blnOK;
my $str = capture { $blnOK = print_page() };
ok($blnOK);
ok($str =~ /whatever/);


Thoughts to improve this? Are there are other functions like this that are needed, or is there a place that this function "belongs"? (I know it needs to be cleaned up.)

I covet your comments ...




Needs local()

Dom2 on 2003-08-19T16:47:39

Rather than fiddling with select(), you might want to say local *STDOUT = IO::String->new or something like it so that STDOUT gets restored even when the code itself dies.

Hmmm, I'm not sure that does exactly the same thing, but it might be worth a try...

-Dom

there's also SelectSaver :)

WebDragon on 2003-08-19T18:48:44

           use SelectSaver;

           {
              my $saver = new SelectSaver(FILEHANDLE);
              # FILEHANDLE is selected
           }
           # previous handle is selected

Not sure if you can use IO::String->new() in there, but it could be worth looking at

Too simplistic.

schwern on 2003-08-19T20:52:36

Your solution of using select() will only work for this:

        print "foo";

but not for this:

        print STDOUT "foo";

nor for anything but the currently selected filehandle.

A more general solution is in TieOut.pm of which copies are scattered around in t/lib directories of various modules, a little invention of chromatic's. Here's one. http://search.cpan.org/src/MSCHWERN/ExtUtils-MakeMaker-6.16/t/lib/. Here's an example of its use. http://search.cpan.org/src/MSCHWERN/ExtUtils-MakeMaker-6.16/t/prompt.t That also shows TieIn for input filehandles.

Yes, one of these days I'll get around to writing Test::Filehandles. Hey, someone could pay me to write it! ;)

Your generalized solution is Too simplistic.

heusserm on 2003-08-20T12:51:40

I don't think your proposed solution works in all cases under perl 5.6.1.

For example:

$r = *STDOUT;
print $r "foo\n";

or

print stdout "foo\n";

(Tying STDOUT won't tie stdout)

Of course, that's fixed in 5.8, but we're not using 5.8.

sigh.

(Most of this from Jeff Klein, who has hubris, but is too lazy to get his own account on use.perl.org ...)

Fork

jdavidb on 2003-08-20T18:03:58

As an alternative approach, how about forking and piping to yourself?