On Fri Jun 22 18:45:22 2007, [EMAIL PROTECTED] wrote: > Write unit tests for config/inter/progs.pm, > the module whose functionality executes Parrot > configuration step inter::progs. >
See patch attached, which includes two testfiles plus a small package, stuffed under t/configure/testlib, which facilitates testing of prompts: Tie::Filehandle::Preempt::Stdin (taken from CPAN). As with other patches, I'll commit this to trunk in about 3 days unless someone objects. kid51
Index: MANIFEST =================================================================== --- MANIFEST (revision 20840) +++ MANIFEST (working copy) @@ -1,7 +1,7 @@ # ex: set ro: # $Id$ # -# generated by tools/dev/mk_manifest_and_skip.pl Sat Aug 25 01:42:41 2007 UT +# generated by tools/dev/mk_manifest_and_skip.pl Sat Aug 25 17:41:30 2007 UT # # See tools/dev/install_files.pl for documentation on the # format of this file. @@ -2908,11 +2908,14 @@ t/configure/103-init_install.t [] t/configure/104-init_miniparrot.t [] t/configure/106-init_headers.t [] +t/configure/107-inter_progs.01.t [] +t/configure/107-inter_progs.02.t [] t/configure/base.t [] t/configure/config_steps.t [] t/configure/data.t [] t/configure/step.t [] t/configure/testlib/Make_VERSION_File.pm [] +t/configure/testlib/Tie/Filehandle/Preempt/Stdin.pm [] t/configure/testlib/init/alpha.pm [] t/configure/testlib/init/beta.pm [] t/configure/testlib/init/delta.pm [] Index: t/configure/107-inter_progs.01.t =================================================================== --- t/configure/107-inter_progs.01.t (revision 0) +++ t/configure/107-inter_progs.01.t (revision 0) @@ -0,0 +1,111 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 107-inter_progs.01.t + +use strict; +use warnings; +use Test::More tests => 24; +use Carp; +use Data::Dumper; +use lib qw( . lib ../lib ../../lib t/configure/testlib ); +use_ok('config::init::defaults'); +use_ok('config::init::install'); +use_ok('config::init::hints'); +use_ok('config::inter::progs'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::IO::Capture::Mini; +use Parrot::Configure::Test qw( test_step_thru_runstep); +use Tie::Filehandle::Preempt::Stdin; + +=for hints_for_testing Testing and refactoring of inter::progs should +entail understanding of issues discussed in the following RT tickets: +http://rt.perl.org/rt3/Ticket/Display.html?id=43174; +http://rt.perl.org/rt3/Ticket/Display.html?id=43173; and +http://rt.perl.org/rt3/Ticket/Display.html?id=41168. You will have to +determine a way to test a user response to a prompt. + +=cut + +my $args = process_options( { + argv => [ q{--ask} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new; + +test_step_thru_runstep($conf, q{init::defaults}, $args); +test_step_thru_runstep($conf, q{init::install}, $args); +test_step_thru_runstep($conf, q{init::hints}, $args); + +my (@prompts, $object, @entered); [EMAIL PROTECTED] = map { q{foo_} . $_ } + qw| alpha beta gamma delta epsilon zeta eta theta iota kappa |; +$object = tie *STDIN, 'Tie::Filehandle::Preempt::Stdin', @prompts; +can_ok('Tie::Filehandle::Preempt::Stdin', ('READLINE')); +isa_ok($object, 'Tie::Filehandle::Preempt::Stdin'); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::progs}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); + +$task = $conf->steps->[3]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); + +# need to capture the --verbose output, because the fact that it does not end +# in a newline confuses Test::Harness +{ + my $tie_out = tie *STDOUT, "Parrot::IO::Capture::Mini" + or croak "Unable to tie"; + $ret = $step->runstep($conf); + my @more_lines = $tie_out->READLINE; + ok(@more_lines, "prompts were captured"); + ok(defined $ret, "$step_name runstep() returned defined value"); +} + +$object = undef; +untie *STDIN; + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +107-inter_progs.01.t - test config::inter::progs + +=head1 SYNOPSIS + + % prove t/configure/107-inter_progs.01.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::progs. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::progs, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/107-inter_progs.01.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: t/configure/107-inter_progs.02.t =================================================================== --- t/configure/107-inter_progs.02.t (revision 0) +++ t/configure/107-inter_progs.02.t (revision 0) @@ -0,0 +1,111 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 107-inter_progs.02.t + +use strict; +use warnings; +use Test::More tests => 24; +use Carp; +use Data::Dumper; +use lib qw( . lib ../lib ../../lib t/configure/testlib ); +use_ok('config::init::defaults'); +use_ok('config::init::install'); +use_ok('config::init::hints'); +use_ok('config::inter::progs'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::IO::Capture::Mini; +use Parrot::Configure::Test qw( test_step_thru_runstep); +use Tie::Filehandle::Preempt::Stdin; + +=for hints_for_testing Testing and refactoring of inter::progs should +entail understanding of issues discussed in the following RT tickets: +http://rt.perl.org/rt3/Ticket/Display.html?id=43174; +http://rt.perl.org/rt3/Ticket/Display.html?id=43173; and +http://rt.perl.org/rt3/Ticket/Display.html?id=41168. You will have to +determine a way to test a user response to a prompt. + +=cut + +my $args = process_options( { + argv => [ q{--ask}, q{--debugging=0} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new; + +test_step_thru_runstep($conf, q{init::defaults}, $args); +test_step_thru_runstep($conf, q{init::install}, $args); +test_step_thru_runstep($conf, q{init::hints}, $args); + +my (@prompts, $object, @entered); [EMAIL PROTECTED] = map { q{foo_} . $_ } + qw| alpha beta gamma delta epsilon zeta eta theta iota |; +$object = tie *STDIN, 'Tie::Filehandle::Preempt::Stdin', @prompts; +can_ok('Tie::Filehandle::Preempt::Stdin', ('READLINE')); +isa_ok($object, 'Tie::Filehandle::Preempt::Stdin'); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::progs}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); + +$task = $conf->steps->[3]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); + +# need to capture the --verbose output, because the fact that it does not end +# in a newline confuses Test::Harness +{ + my $tie_out = tie *STDOUT, "Parrot::IO::Capture::Mini" + or croak "Unable to tie"; + $ret = $step->runstep($conf); + my @more_lines = $tie_out->READLINE; + ok(@more_lines, "prompts were captured"); + ok(defined $ret, "$step_name runstep() returned defined value"); +} + +$object = undef; +untie *STDIN; + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +107-inter_progs.02.t - test config::inter::progs + +=head1 SYNOPSIS + + % prove t/configure/107-inter_progs.02.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::progs. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::progs, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/107-inter_progs.02.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: t/configure/testlib/Tie/Filehandle/Preempt/Stdin.pm =================================================================== --- t/configure/testlib/Tie/Filehandle/Preempt/Stdin.pm (revision 0) +++ t/configure/testlib/Tie/Filehandle/Preempt/Stdin.pm (revision 0) @@ -0,0 +1,142 @@ +package Tie::Filehandle::Preempt::Stdin; +$VERSION = "0.01"; +use strict; +use Carp; + +sub TIEHANDLE { + my $class = shift; + my @lines = @_; + bless [EMAIL PROTECTED], $class; +} + +sub READLINE { + my $self = shift; + if (@$self) { + shift @$self; + } else { + croak "List of prompt responses has been exhausted: $!"; + } +} + +1; + +##### DOCUMENTATION ##### + +=head1 NAME + +Tie::Filehandle::Preempt::Stdin - Preempt STDIN during testing. + +=head1 SYNOPSIS + + use Tie::Filehandle::Preempt::Stdin; + @prompts = qw| alpha beta gamma |; + $object = tie *STDIN, 'Tie::Filehandle::Preempt::Stdin', @prompts; + +=head1 DESCRIPTION + +Suppose a program requires manual input from the keyboard operator. +How do we test that we have properly handled operator input? More +specifically, how do we incorporate testing for user input in files +built on Perl's standard testing apparatus (C<Test::Simple>, +C<Test::More>, etc.)? + +Tie::Filehandle::Preempt::Stdin offers one way to do it -- a relatively +simple and unsophisticated todo it. The most difficult part is +analyzing the program to be tested so that you recognize all the points +at which input is needed via STDIN. This in turn requires an +understanding of all the different branches your program flow can take +in response to standard input. Once you know that, you construct a list +of dummy data that will be fed to each test at the points the program, +when put into production, would normally prompt for operator input. +This list of dummy data 'pre-empts' standard input via a tie of +filehandle STDIN; hence, the module's name. + +=head1 USAGE + + @prompts = qw| alpha beta gamma |; + $object = tie *STDIN, 'Tie::Filehandle::Preempt::Stdin', @prompts; + + print "Enter item 1: "; + chomp($entry = <STDIN>); + # 'alpha' is supplied in lieu of standard input; + # do something with $entry + + print "Enter item 2: "; + chomp($entry = <STDIN>); + # 'beta' is supplied in lieu of standard input; + # do something with $entry + + print "Enter item 3: "; + chomp($entry = <STDIN>); + # 'gamma' is supplied in lieu of standard input; + # do something with $entry + +Should the number of elements in C<@prompts> be less than the number of +points at which a given test prompts for operator input, you will get an +error message: + + "List of prompt responses has been exhausted" + +and the program will C<croak>. + +=head1 BUGS + +Tie::Filehandle::Preempt::Stdin does not work properly when the source +code being tested uses only the Perl diamond operator for standard input. + + print "Enter room whose data you wish to enter: "; + chomp ($try = <>); + +This doesn't work; your program will hang. You have to hard-code +C<STDIN> instead. + + chomp ($try = <STDIN>); + +I don't know why this happens. If this bothers you, look at +C<IO::Scalar> which is reported to handle the diamond operator properly, +but which, IMHO, has a more complex interface. + +=head1 SUPPORT + +Contact author or post on [EMAIL PROTECTED] + +=head1 AUTHOR + +James E Keenan. CPAN ID: JKEENAN. Mail to: jkeenan [at] cpan [dot] org. + +=head1 ACKNOWLEDGEMENTS + +The author benefitted from -- but did not always agree with -- comments +from the following members of Perlmonks: chromatic, Revelation, +tmoertel, NiJo and dragonchild. + +Thanks to Michael G Schwern and Kevin Scaldeferri for answering +questions on the perl.qa mailing list. + +=head1 COPYRIGHT + +Copyright 2005 James E Keenan. +This program is free software; you can redistribute +it and/or modify it under the same terms as Perl itself. + +The full text of the license can be found in the +LICENSE file included with this module. + +Last revision: Apr 17 2005. + +=head1 SEE ALSO + +perltie(1). + +I<Programming Perl> (3rd ed.), Larry Wall, Tom Christiansen +and Jon Orwant. O'Reilly & Associates, 1991. Chapter 14: Tied +Variables: section on ''Tying Filehandles,'' p. 384 ff. + +Perlmonks discussion starting at: +L<http://www.perlmonks.org/index.pl?node_id=430997>. + +Postings on perl.qa at: +L<http://www.nntp.perl.org/group/perl.qa/4074> and +L<http://www.nntp.perl.org/group/perl.qa/4076>. + +=cut Property changes on: t/configure/testlib/Tie/Filehandle/Preempt/Stdin.pm ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native