in reply to Pre-empting STDIN during Testing

That's the best way I've found. You might find the tests for Term::Complete interesting; that was the most challenging test I've ever written, I/O wise.

I don't have time to check right now, but can you tie *ARGV to fix readline() without a filehandle or a scalar? Something in the back of my brain thinks I've done this before.

Replies are listed 'Best First'.
Re^2: Pre-empting STDIN during Testing
by jkeenan1 (Deacon) on Feb 15, 2005 at 21:36 UTC
    In my posting on pre-empting STDIN during testing yesterday, I noted that my provisional solution had the following problem:

    If the code being tested calls for input from STDIN more times than there are elements in the array tied to STDIN (or if those elements are undef), and if the user prompt is located (as is likely) within a while (<>) loop, then the program goes into an infinite loop because all elements of the tied array have been shifted off.

    A simple change in Preempt::Stdin::READLINE() solves this problem: Croak if there are no elements left in the list provided to the subroutine; then capture and examine the error in the testing script.

    Here's the revised Preempt::Stdin:

    And here's the revised testing script, starting with the two passing tests from yesterday and followed by a new test in which the error is captured and examined.

    Two additional points.

    First, as mentioned yesterday, if you wanted to capture all those prompt messages going to STDOUT, you could do so with IO::Capture::Stdout.

    Second, if the subroutine being tested were more complex than the one above, there is a good chance that, in the case of insufficient arguments, warnings would be generated due to uninitialized variables. Since those warnings would be expected, you would probably want to suppress them during testing. You could so by defining a subroutine

    sub _capture { my $str = $_[0]; }

    and then calling

    local $SIG{__WARN__} = \&_capture; tie *STDIN, 'Preempt::Stdin', @lines; ... # as before

    at the top of the block.

    To give credit where credit is due: The idea of capturing the error from a deliberately failing test and examining it with Test::More::like() was picked up from monk dha during our joint work on the Phalanx project. And the idea of capturing warnings within a block was picked up from (IIRC) Benjamin Goldberg on c.l.p.misc a couple of years back.

    Jim Keenan