Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re: Outputting input prompt with prove

by davido (Cardinal)
on Aug 05, 2019 at 15:09 UTC ( [id://11103947]=note: print w/replies, xml ) Need Help??


in reply to Outputting input prompt with prove

This is a tricky problem, but it has various solutions.

One solution is to use IPC::Open3, and to test your script by writing to STDIN programatically, and reading from STDOUT. It would be a lot more convenient to just use a module like Capture::Tiny, but that module doesn't really help you solve the writing to STDIN problem very well. IPC::Run may be easier to use for this.

Another solution is to convert your prompting and input code to use ExtUtils::MakeMaker's prompt function. This function allows you to provide a default value, but also allows you to set the environment variable PERL_MM_USE_DEFAULT to tell prompt to use that default value in lieu of reading from STDIN. It's sort of an odd state of evolution that ExtUtils::MakeMaker contains a prompt function, but ExtUtils::MakeMaker is a core Perl module, as baked into the Perl distribution as strict.

Though it introduces a dependency to do so, IO::Prompt::Tiny puts the function into a module that is less of a kitchen sink, and more appropriately named for what it provides. It still offers compatibility with the PERL_MM_USE_DEFAULT environment variable. Here is an example script using it:

#!/usr/bin/env perl use strict; use warnings; use IO::Prompt::Tiny qw(prompt); my $input = prompt('Enter: ', 50); print "$input\n";

And here is a sample test:

use Test::More; use Capture::Tiny qw(capture); my ($stdout, $stderr, $exit) = capture { local $ENV{'PERL_MM_USE_DEFAULT'} = 1; system('/usr/bin/env', 'perl', './mytest.pl'); }; ok 0 == $exit, 'Clean exit code.'; like $stderr, qr/^\QIs interactive? No/, 'Detected non-interactive mod +e.'; is $stdout, "Enter: [50] 50\n50\n", 'Correct output.';

But this still exposes a weakness in going about testing by looking at STDOUT; you're testing at the highest level, and are unable to examine what's going on at lower levels. It's difficult to unit test. If you went the route of using a modulino you could reconfigure your script for better testability. Modulinos are described in the OReilly book, "Mastering Perl", and also in various online resources, one of the earliest of which is http://www.drdobbs.com/scripts-as-modules/184416165.

By converting to a modulino, breaking functionality into sensible subroutines, and then creating appropriate wrappers around the IO boundaries you can develop tests that validate both the top level code through the use of IO capturing techniques demonstrated above, and also at the unit level. For the unit level tests many of them could mock an output subroutine to avoid hitting STDOUT at all, similar to how prompt allows for hinting STDIN.


Dave

Replies are listed 'Best First'.
Re^2: Outputting input prompt with prove
by Anonymous Monk on Aug 06, 2019 at 01:50 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11103947]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-04-19 07:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found