File Coverage

blib/lib/Test/Run/CmdLine.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Test::Run::CmdLine;
2              
3 5     5   40536 use warnings;
  5         9  
  5         151  
4 5     5   26 use strict;
  5         10  
  5         138  
5              
6 5     5   92 use 5.008;
  5         21  
  5         158  
7              
8 5     5   23 use Carp;
  5         18  
  5         390  
9 5     5   1303 use UNIVERSAL::require;
  5         1848  
  5         34  
10 5     5   14686 use YAML::XS ();
  5         17853  
  5         153  
11              
12 5     5   9859 use Test::Run::Base;
  0            
  0            
13              
14             use Test::Run::Iface;
15             use Test::Run::Obj;
16              
17             =head1 NAME
18              
19             Test::Run::CmdLine - Analyze tests from the command line using Test::Run
20              
21             =cut
22              
23             use vars (qw($VERSION));
24              
25             $VERSION = '0.0126';
26              
27             use Moose;
28              
29             extends ('Test::Run::Base');
30              
31             =head1 SYNOPSIS
32              
33             use Test::Run::CmdLine;
34              
35             my $tester = Test::Run::CmdLine->new(
36             {
37             'test_files' => ["t/one.t", "t/two.t"],
38             },
39             );
40              
41             $tester->run();
42              
43             =cut
44              
45             has 'backend_class' => (is => "rw", isa => "Str",
46             default => "Test::Run::Iface"
47             );
48             has 'backend_params' => (is => "rw", isa => "HashRef");
49             has 'backend_plugins' => (is => "rw", isa => "ArrayRef",
50             default => sub { [] },
51             );
52             has 'backend_env_args' => (is => "rw", isa => "ArrayRef",
53             default => sub { [] },
54             );
55             has 'test_files' => (is => "rw", isa => "ArrayRef");
56              
57             sub BUILD
58             {
59             my $self = shift;
60              
61             $self->_collect_backend_plugins();
62              
63             return;
64             }
65              
66             sub _process_args
67             {
68             my ($self, $args) = @_;
69             if (exists($args->{backend_params}))
70             {
71             $self->backend_params($args->{backend_params});
72             }
73              
74             return 0;
75             }
76              
77             =head1 Interface Functions
78              
79             =head2 $tester = Test::Run::CmdLine->new({'test_files' => \@test_files, ....});
80              
81             Initializes a new testing front end. C<test_files> is a named argument that
82             contains the files to test.
83              
84             Other named arguments are:
85              
86             =over 4
87              
88             =item backend_params
89              
90             This is a hash of named parameters to be passed to the backend class (derived
91             from L<Test::Run::Obj>.)
92              
93             =item driver_class
94              
95             This is the backend class that will be instantiated and used to perform
96             the processing. Defaults to L<Test::Run::Obj>.
97              
98             =back
99              
100             =head2 $tester->run()
101              
102             Actually runs the tests on the command line.
103              
104             TODO : Write more.
105              
106             =head2 BUILD
107              
108             For Moose.
109              
110             =cut
111              
112             sub run
113             {
114             my $self = shift;
115             my $backend_class = $self->backend_class();
116             $backend_class->require();
117             if ($@)
118             {
119             die $@;
120             }
121             foreach my $plugin (@{$self->_calc_plugins_for_ISA()})
122             {
123             $plugin->require();
124             if ($@)
125             {
126             die $@;
127             }
128             {
129             no strict 'refs';
130             push @{"${backend_class}::ISA"}, $plugin;
131             }
132             }
133              
134             # Finally - put Test::Run::Obj there.
135             {
136             no strict 'refs';
137             push @{"${backend_class}::ISA"}, "Test::Run::Obj";
138             }
139              
140             my $backend = $backend_class->new(
141             {
142             'test_files' => $self->test_files(),
143             @{$self->get_backend_args()},
144             },
145             );
146              
147             return $backend->runtests();
148             }
149              
150             =head1 Environment Variables
151              
152             The following environment variables (C<%ENV>) affect the behaviour of
153             Test::Run::CmdLine:
154              
155             =over 4
156              
157             =item HARNESS_COLUMNS
158              
159             This determines the width of the terminal (sets C<'Columns'>) in
160             L<Test::Run::Obj>). If not specified, it will be determined according
161             to the C<COLUMNS> environment variable, that is normally specified by
162             the terminal.
163              
164             =item HARNESS_DEBUG
165              
166             Triggers the C<'Debug'> option in Test::Run::Obj. Meaning, it will print
167             debugging information about itself as it runs the tests.
168              
169             =item HARNESS_FILELEAK_IN_DIR
170              
171             This variable points to a directory that will be monitored. After each
172             test file, the module will check if new files appeared in the direcotry
173             and report them.
174              
175             It is advisable to give an absolute path here. If it is relative, it would
176             be relative to the current working directory when C<$tester-E<gt>run()> was
177             called.
178              
179             =item HARNESS_NOTTY
180              
181             Triggers the C<'NoTty'> option in Test::Run::Obj. Meaning, it causes
182             Test::Run::CmdLine not to treat STDOUT as if it were a console. In this
183             case, it will not emit more frequent progress reports using carriage
184             returns (C<"\r">s).
185              
186             =item HARNESS_PERL
187              
188             Specifies the C<'Test_Interpreter'> variable of L<Test::Run::Obj>. This allows
189             specifying a different Perl interprter to use besides C<$^X>.
190              
191             =item HARNESS_PERL_SWITCHES
192              
193             Specifies the C<'Switches'> variable of L<Test::Run::Obj>. This allows
194             specifying more switches to the Perl interpreter.
195              
196             =item HARNESS_TIMER
197              
198             This variable triggers the C<'Timer'> option in Test::Run::Obj. What it
199             does is causes the time that took for tests to run to be displayed.
200              
201             =item HARNESS_VERBOSE
202              
203             Triggers the C<'Verbose'> option in Test::Run::Obj. Meaning, it emits
204             the standard output of the test files while they are processed.
205              
206             =back
207              
208             =head1 Internal Functions
209              
210             =head2 my $args_array_ref = $tester->get_backend_args()
211              
212             Calculate and retrieve the arguments for the backend class (that inherits
213             from L<Test::Run::Obj>) as a single array reference. Currently it appends
214             the arguments of get_backend_env_args() to that of get_backend_init_args().
215              
216             =cut
217              
218             sub get_backend_args
219             {
220             my $self = shift;
221              
222             return $self->accum_array(
223             {
224             method => "private_backend_args",
225             }
226             );
227             }
228              
229             =head2 $self->private_backend_args()
230              
231             Calculates the get_backend_args()-specific arguments for this class.
232              
233             =cut
234              
235             sub private_backend_args
236             {
237             my $self = shift;
238              
239             $self->get_backend_env_args();
240              
241             my $init_args = $self->get_backend_init_args();
242              
243             return [@{$self->backend_env_args()}, @$init_args];
244             }
245              
246             =head2 $tester->get_backend_env_args()
247              
248             Calculate the arguments for the backend class, that originated
249             from the environment (%ENV), and puts them in C<$tester->backend_env_args()>
250              
251             =cut
252              
253             sub _get_direct_backend_env_mapping
254             {
255             my $self = shift;
256              
257             return $self->accum_array(
258             {
259             method => "private_direct_backend_env_mapping",
260             }
261             );
262             }
263              
264             =head2 $self->private_direct_backend_env_mapping()
265              
266             The return value of this method is collected from every class, and adapted
267             to the direct backend environment mapping.
268              
269             =cut
270              
271             sub private_direct_backend_env_mapping
272             {
273             my $self = shift;
274             return [
275             { 'env' => "HARNESS_FILELEAK_IN_DIR", 'arg' => "Leaked_Dir", },
276             { 'env' => "HARNESS_VERBOSE", 'arg' => "Verbose", },
277             { 'env' => "HARNESS_DEBUG", 'arg' => "Debug", },
278             { 'env' => "COLUMNS", 'arg' => "Columns", },
279             { 'env' => "HARNESS_COLUMNS", 'arg' => "Columns", },
280             { 'env' => "HARNESS_TIMER", 'arg' => "Timer", },
281             { 'env' => "HARNESS_NOTTY", 'arg' => "NoTty", },
282             { 'env' => "HARNESS_PERL", 'arg' => "Test_Interpreter", },
283             { 'env' => "HARNESS_PERL_SWITCHES", 'arg' => "Switches_Env", },
284             ];
285             }
286              
287             sub _get_non_direct_backend_env_mapping
288             {
289             my $self = shift;
290              
291             return $self->accum_array(
292             {
293             method => "private_non_direct_backend_env_mapping",
294             }
295             );
296             }
297              
298             sub _get_backend_env_mapping
299             {
300             my $self = shift;
301              
302             return
303             [
304             (map { +{ type => "direct", %$_ } } @{$self->_get_direct_backend_env_mapping()}),
305             @{$self->_get_non_direct_backend_env_mapping()},
306             ];
307             }
308              
309             sub _handle_backend_env_spec
310             {
311             my ($self, $spec) = @_;
312              
313             my $type = $spec->{type};
314             my $env = $spec->{env};
315              
316             if (exists($ENV{$env}))
317             {
318             my $sub = $self->can("_backend_spec_handler_for_$type");
319              
320             if (! $sub)
321             {
322             confess "Cannot find type handler for $type!";
323             }
324              
325             $sub->(
326             $self,
327             $spec,
328             );
329             }
330             }
331              
332             sub _backend_spec_handler_for_direct
333             {
334             my ($self, $spec) = @_;
335              
336             my $arg = $spec->{arg};
337             my $env = $spec->{env};
338              
339             push @{$self->backend_env_args()},
340             ($arg => $ENV{$env});
341             }
342              
343             sub _backend_spec_handler_for_yamldata
344             {
345             my ($self, $spec) = @_;
346              
347             my $arg = $spec->{arg};
348             my $env = $spec->{env};
349              
350             push @{$self->backend_env_args()},
351             ($arg => YAML::XS::LoadFile($ENV{$env}));
352             }
353              
354             sub _calc_backend_env_var_map
355             {
356             my ($self, $mapping_string) = @_;
357              
358             my @assignments = split(/\s*;\s*/, $mapping_string);
359             return
360             +{
361             map { /\A([^=]*)=(.*)\z/ms ? ($1 => $2) : () }
362             @assignments
363             };
364             }
365              
366             sub _backend_spec_handler_for_varmap
367             {
368             my ($self, $spec) = @_;
369              
370             my $arg = $spec->{arg};
371             my $env = $spec->{env};
372              
373             push @{$self->backend_env_args()},
374             ($arg => $self->_calc_backend_env_var_map($ENV{$env}));
375             }
376              
377             sub get_backend_env_args
378             {
379             my $self = shift;
380             foreach my $spec (@{$self->_get_backend_env_mapping()})
381             {
382             $self->_handle_backend_env_spec($spec);
383             }
384              
385             return 0;
386             }
387              
388             =head2 my $args_array_ref = $tester->get_backend_init_args()
389              
390             Calculate and return the arguments for the backend class, that originated
391             from the arguments passed to the (front-end) object from its constructor.
392              
393             =cut
394              
395             sub get_backend_init_args
396             {
397             my $self = shift;
398             my @args;
399             if (defined($self->backend_params()))
400             {
401             push @args, (%{$self->backend_params()});
402             }
403             return \@args;
404             }
405              
406             sub _calc_plugins_for_ISA
407             {
408             my $self = shift;
409             return
410             [
411             map { $self->_calc_single_plugin_for_ISA($_) }
412             @{$self->backend_plugins()}
413             ];
414             }
415              
416             sub _calc_single_plugin_for_ISA
417             {
418             my $self = shift;
419             my $p = shift;
420             return "Test::Run::Plugin::$p";
421             }
422              
423             =head2 $self->private_backend_plugins()
424              
425             Calculates the backend plugins specific for this class. They will be collected
426             to formulate a list of plugins that will be C<add_to_backend_plugins()>'ed.
427              
428             =cut
429              
430             sub _get_backend_plugins_accumulation
431             {
432             my $self = shift;
433              
434             return [reverse(@{$self->accum_array(
435             {
436             method => "private_backend_plugins",
437             }
438             )})];
439             }
440              
441             sub _collect_backend_plugins
442             {
443             my $self = shift;
444              
445             foreach my $plug (@{$self->_get_backend_plugins_accumulation()})
446             {
447             $self->add_to_backend_plugins($plug);
448             }
449              
450             return;
451             }
452              
453             =head2 $self->add_to_backend_plugins($plugin)
454              
455             Appends a plugin to the plugins list. Useful in front-end plug-ins.
456              
457             =cut
458              
459             sub add_to_backend_plugins
460             {
461             my $self = shift;
462             my $plugin = shift;
463             unshift @{$self->backend_plugins()}, $plugin;
464             }
465              
466             =head1 AUTHORS
467              
468             Shlomi Fish, C<< <shlomif@iglu.org.il> >>
469              
470             =head1 BUGS
471              
472             Please report any bugs or feature requests to
473             C<bug-test-run-cmdline@rt.cpan.org>, or through the web interface at
474             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Run-CmdLine>.
475             I will be notified, and then you'll automatically be notified of progress on
476             your bug as I make changes.
477              
478             =head1 SUPPORT
479              
480             You can find documentation for this module with the perldoc command.
481              
482             perldoc Test::Run::CmdLine
483              
484             You can also look for information at:
485              
486             =over 4
487              
488             =item * AnnoCPAN: Annotated CPAN documentation
489              
490             L<http://annocpan.org/dist/Test::Run::CmdLine>
491              
492             =item * CPAN Ratings
493              
494             L<http://cpanratings.perl.org/d/Test::Run::CmdLine>
495              
496             =item * RT: CPAN's request tracker
497              
498             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test::Run::CmdLine>
499              
500             =item * Search CPAN
501              
502             L<http://search.cpan.org/dist/Test::Run::CmdLine/>
503              
504             =back
505              
506             =head1 SOURCE AVAILABILITY
507              
508             The latest source of Test::Run::CmdLine is available from the Test::Run
509             BerliOS Subversion repository:
510              
511             L<https://svn.berlios.de/svnroot/repos/web-cpan/Test-Harness-NG/>
512              
513             =head1 ACKNOWLEDGEMENTS
514              
515             =head1 COPYRIGHT & LICENSE
516              
517             Copyright 2005 Shlomi Fish, all rights reserved.
518              
519             This program is released under the MIT X11 License.
520              
521             =cut
522              
523             1; # End of Test::Run::CmdLine