File Coverage

blib/lib/Test/FITesque/Test.pm
Criterion Covered Total %
statement 73 73 100.0
branch 26 26 100.0
condition 14 15 93.3
subroutine 9 9 100.0
pod 4 4 100.0
total 126 127 99.2


line stmt bran cond sub pod time code
1             package Test::FITesque::Test;
2              
3 6     6   34393 use strict;
  6         6  
  6         150  
4 6     6   21 use warnings;
  6         7  
  6         100  
5              
6 6     6   2904 use Module::Load;
  6         4137  
  6         23  
7 6     6   213 use Test::Builder;
  6         7  
  6         2966  
8              
9             our $TEST_BUILDER;
10             our $METHOD_DETAIL_VERBOSE;
11              
12              
13             =head1 NAME
14              
15             Test::FITesque::Test - A FITesque test
16              
17             =head1 SYNOPSIS
18              
19             my $test = Test::FITesque::Test->new();
20              
21             # add test rows
22             $test->add( ... );
23             $test->add( ... );
24              
25             # return number of TAP tests
26             $test->test_count();
27              
28             $test->run_tests();
29              
30             =head1 DESCRIPTION
31              
32             =head1 METHODS
33              
34             =head2 new
35              
36             my $test = Test::FITesque::Test->new();
37              
38             This is a simple constructor. It takes a hashref of options:
39              
40             =over
41              
42             =item data
43              
44             This is an arrayref of arrayrefs for the FITesque run.
45              
46             =back
47              
48             Please note that the first test row that is added must be the FITesque fixture
49             class name, followed by the arguments to be passed to its constructor.
50              
51             =cut
52              
53             sub new {
54 26     26 1 5518 my ($class, $args) = @_;
55 26   100     84 $args ||= {};
56 26         42 my $self = bless $args, $class;
57 26         47 return $self;
58             }
59              
60             =head2 add
61              
62             $test->add(qw(Foo::Fixture some constructor args));
63             $test->add('click button', 'search');
64              
65             This method allows you to add FITesque test rows individually. As with the data
66             option in the constructor, the first row added must be the Fixture class name
67             and its constructor arguments.
68              
69             =cut
70              
71             sub add {
72 45     45 1 109 my ($self, @args) = @_;
73 45   100     112 $self->{data} ||= [];
74              
75 45         37 push @{ $self->{data} }, [@args];
  45         97  
76             }
77              
78             =head2 test_count
79              
80             my $count = $test->test_count();
81              
82             This method returns the number of TAP tests expected to be run during the
83             test run.
84              
85             =cut
86              
87             sub test_count {
88 36     36 1 325 my ($self) = @_;
89 36   100     74 my $data = $self->{data} || [];
90            
91 36 100       59 if(@$data){
92 35         47 my ($fixture_class) = $self->_load_fixture_class();
93            
94 33         33 my $count = 0;
95 33         66 for my $test_row ( @$data[ 1..( scalar(@$data) -1) ]){
96 44         42 my $method_string = $test_row->[0];
97 44   100     98 my $test_count = $fixture_class->method_test_count($method_string) || 0;
98 44         71 $count += $test_count;
99             }
100              
101 33         89 return $count;
102             }
103            
104 1         4 return 0;
105             }
106              
107             =head2 run_tests
108              
109             $test->run_tests();
110              
111             This method will run the FITesque test based upon the data supplied.
112              
113             =cut
114              
115             sub run_tests {
116 26     26 1 1276 my ($self) = @_;
117 26   100     62 my $data = $self->{data} || [];
118            
119 26 100       36 if(@$data){
120 25         39 my ($fixture_class, @fixture_args) = $self->_load_fixture_class();
121              
122 23         21 my $fixture_object;
123 23 100       45 if(!defined $self->{__test_has_run__}){
124 22         69 @fixture_args = $fixture_class->parse_arguments(@fixture_args);
125 22         68 $fixture_object = $fixture_class->new(@fixture_args);
126 22         37 $self->{__test_has_run__} = 1;
127             } else {
128 1         7 die q{Attempted to run test more than once};
129             }
130              
131             # Deal with being called directly or as part of a suite
132 22         43 my ($pkg) = caller();
133 22 100       266 if(!$pkg->isa('Test::FITesque::Suite')){
134 10 100       24 my $Builder = $TEST_BUILDER ? $TEST_BUILDER : Test::Builder->new();
135 10         29 $Builder->exported_to(__PACKAGE__);
136              
137 10 100 66     59 if ( $Builder->isa('Test::FakeBuilder') || !$Builder->has_plan) {
138 8 100       12 if( my $count = $self->test_count() ){
139 4         15 $Builder->expected_tests($count);
140             } else {
141 4         11 $Builder->no_plan();
142             }
143             }
144             }
145            
146             # early bail out in case of unavailable methods
147             # - We do this as a seperate step as the method called could take a long
148             # time, which would mean that you'd only fail halfway through a long
149             # test run.
150 22         70 for my $test_row (@$data[ 1..(scalar(@$data) -1) ]){
151 33         39 my $method_string = $test_row->[0];
152 33 100       60 if( !$fixture_object->parse_method_string($method_string) ){
153 1         12 die qq{Unable to run tests, no method available for action "$method_string"}
154             }
155             }
156              
157 21         49 for my $test_row ( @$data[ 1..( scalar(@$data) -1) ]){
158 32 100       1199 my $Builder = $TEST_BUILDER ? $TEST_BUILDER : Test::Builder->new();
159 32         59 my ($method_string, @args) = @$test_row;
160 32         58 my $method = $fixture_object->parse_method_string($method_string);
161 32 100       73 die "No method exists for '$method_string'" if !defined $method;
162              
163 31   100     54 my $test_count = $fixture_object->method_test_count($method_string) || 0;
164 31         65 my $msg = "running '$method_string' in class '$fixture_class' ($test_count tests)";
165 31 100       51 $Builder->diag( $msg ) if $METHOD_DETAIL_VERBOSE;
166              
167 31         207 @args = $fixture_object->parse_arguments(@args);
168 31         66 $fixture_object->$method(@args);
169             }
170              
171             }else{
172 1         7 die "Attempted to run empty test";
173             }
174            
175             }
176              
177             sub _load_fixture_class {
178 60     60   63 my ($self) = @_;
179 60         54 my $data = $self->{data};
180 60         44 my ($class,@args) = @{ $data->[0] };
  60         91  
181            
182 60         57 eval {
183 60         123 load $class;
184             };
185 60 100       5159 die qq{Could not load '$class' fixture: $@} if $@;
186 58 100       242 die qq{Fixture class '$class' is not a FITesque fixture}
187             if !$class->isa(q{Test::FITesque::Fixture});
188              
189 56         100 return ($class, @args);
190             }
191              
192             =head1 AUTHOR
193              
194             Scott McWhirter, C<< >>
195              
196             =head1 COPYRIGHT & LICENSE
197              
198             Copyright 2007 Scott McWhirter, all rights reserved.
199              
200             This program is released under the following license: BSD. Please see the
201             LICENSE file included in this distribution for details.
202              
203             =cut
204              
205             1;