File Coverage

blib/lib/Test/FITesque/Test.pm
Criterion Covered Total %
statement 72 72 100.0
branch 24 24 100.0
condition 12 12 100.0
subroutine 9 9 100.0
pod 4 4 100.0
total 121 121 100.0


line stmt bran cond sub pod time code
1             package Test::FITesque::Test;
2              
3 6     6   101372 use strict;
  6         15  
  6         216  
4 6     6   34 use warnings;
  6         15  
  6         164  
5              
6 6     6   6043 use Module::Load;
  6         7650  
  6         139  
7 6     6   350 use Test::Builder;
  6         14  
  6         9551  
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 17552 my ($class, $args) = @_;
55 26   100     147 $args ||= {};
56 26         79 my $self = bless $args, $class;
57 26         82 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 213 my ($self, @args) = @_;
73 45   100     231 $self->{data} ||= [];
74              
75 45         56 push @{ $self->{data} }, [@args];
  45         206  
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 41     41 1 534 my ($self) = @_;
89 41   100     163 my $data = $self->{data} || [];
90            
91 41 100       129 if(@$data){
92 40         108 my ($fixture_class) = $self->_load_fixture_class();
93            
94 38         60 my $count = 0;
95 38         127 for my $test_row ( @$data[ 1..( scalar(@$data) -1) ]){
96 53         93 my $method_string = $test_row->[0];
97 53   100     298 my $test_count = $fixture_class->method_test_count($method_string) || 0;
98 53         158 $count += $test_count;
99             }
100              
101 38         177 return $count;
102             }
103            
104 1         7 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 8756 my ($self) = @_;
117 26   100     109 my $data = $self->{data} || [];
118            
119 26 100       80 if(@$data){
120 25         78 my ($fixture_class, @fixture_args) = $self->_load_fixture_class();
121              
122 23         43 my $fixture_object;
123 23 100       80 if(!defined $self->{__test_has_run__}){
124 22         132 @fixture_args = $fixture_class->parse_arguments(@fixture_args);
125 22         117 $fixture_object = $fixture_class->new(@fixture_args);
126 22         72 $self->{__test_has_run__} = 1;
127             } else {
128 1         19 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         66 my ($pkg) = caller();
133 22 100       473 if(!$pkg->isa('Test::FITesque::Suite')){
134 10 100       47 my $Builder = $TEST_BUILDER ? $TEST_BUILDER : Test::Builder->new();
135 10         63 $Builder->exported_to(__PACKAGE__);
136              
137 10 100       77 if( my $count = $self->test_count() ){
138 6         32 $Builder->expected_tests($count);
139             } else {
140 4         18 $Builder->no_plan();
141             }
142             }
143            
144             # early bail out in case of unavailable methods
145             # - We do this as a seperate step as the method called could take a long
146             # time, which would mean that you'd only fail halfway through a long
147             # test run.
148 22         728 for my $test_row (@$data[ 1..(scalar(@$data) -1) ]){
149 33         68 my $method_string = $test_row->[0];
150 33 100       101 if( !$fixture_object->parse_method_string($method_string) ){
151 1         22 die qq{Unable to run tests, no method available for action "$method_string"}
152             }
153             }
154              
155 21         88 for my $test_row ( @$data[ 1..( scalar(@$data) -1) ]){
156 32 100       2284 my $Builder = $TEST_BUILDER ? $TEST_BUILDER : Test::Builder->new();
157 32         108 my ($method_string, @args) = @$test_row;
158 32         97 my $method = $fixture_object->parse_method_string($method_string);
159 32 100       122 die "No method exists for '$method_string'" if !defined $method;
160              
161 31   100     92 my $test_count = $fixture_object->method_test_count($method_string) || 0;
162 31         110 my $msg = "running '$method_string' in class '$fixture_class' ($test_count tests)";
163 31 100       79 $Builder->diag( $msg ) if $METHOD_DETAIL_VERBOSE;
164              
165 31         387 @args = $fixture_object->parse_arguments(@args);
166 31         107 $fixture_object->$method(@args);
167             }
168              
169             }else{
170 1         12 die "Attempted to run empty test";
171             }
172            
173             }
174              
175             sub _load_fixture_class {
176 65     65   94 my ($self) = @_;
177 65         114 my $data = $self->{data};
178 65         90 my ($class,@args) = @{ $data->[0] };
  65         173  
179            
180 65         101 eval {
181 65         256 load $class;
182             };
183 65 100       14611 die qq{Could not load '$class' fixture: $@} if $@;
184 63 100       466 die qq{Fixture class '$class' is not a FITesque fixture}
185             if !$class->isa(q{Test::FITesque::Fixture});
186              
187 61         193 return ($class, @args);
188             }
189              
190             =head1 AUTHOR
191              
192             Scott McWhirter, C<< >>
193              
194             =head1 COPYRIGHT & LICENSE
195              
196             Copyright 2007 Scott McWhirter, all rights reserved.
197              
198             This program is released under the following license: BSD. Please see the
199             LICENSE file included in this distribution for details.
200              
201             =cut
202              
203             1;