File Coverage

blib/lib/Test/A8N/File.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Test::A8N::File;
2 1     1   246409 use warnings;
  1         2  
  1         32  
3 1     1   5 use strict;
  1         2  
  1         27  
4              
5             # NB: Moose also enforces 'strict' and warnings;
6 1     1   390 use Moose;
  0            
  0            
7             use YAML::Syck;
8             use Test::A8N::TestCase;
9             use Module::Load;
10             use Storable qw(dclone);
11              
12             has config => (
13             is => q{ro},
14             required => 1,
15             isa => q{HashRef}
16             );
17              
18             my %default_lazy = (
19             required => 1,
20             lazy => 1,
21             is => q{ro},
22             default => sub { die "need to override" },
23             );
24              
25             has filename => (
26             is => q{ro},
27             required => 1,
28             isa => q{Str}
29             );
30              
31             has file_root => (
32             %default_lazy,
33             isa => q{Str},
34             default => sub { return shift->config->{file_root} },
35             );
36              
37             has fixture_base => (
38             %default_lazy,
39             isa => q{Str},
40             default => sub { return shift->config->{fixture_base} },
41             );
42              
43             has verbose => (
44             %default_lazy,
45             isa => q{Int},
46             default => sub { return shift->config->{verbose} },
47             );
48              
49             has data => (
50             %default_lazy,
51             isa => q{ArrayRef},
52             default => sub {
53             my $self = shift;
54             my $content = [];
55             eval {
56             $content = [ LoadFile($self->filename) ];
57             };
58             if ($@) {
59             printf("# YAML syntax error while loading %s: %s\n", $self->filename, $@) if ($self->verbose);
60             }
61             return $content;
62             }
63             );
64              
65             has testcase_class => (
66             %default_lazy,
67             isa => q{Str},
68             default => "Test::A8N::TestCase"
69             );
70              
71             has cases => (
72             %default_lazy,
73             isa => q{ArrayRef},
74             default => sub {
75             my $self = shift;
76             my @cases;
77             my $idx = 0;
78             my $filename = $self->filename;
79             foreach my $case (@{ $self->data }) {
80             my $case = $self->testcase_class->new({
81             'data' => $case,
82             'index' => ++$idx,
83             'filename' => $filename,
84             'config' => dclone( $self->config ),
85             });
86             push @cases, $case if ($case->is_valid);
87             }
88             return \@cases;
89             }
90             );
91              
92             sub filtered_cases {
93             my $self = shift;
94             my ($id) = @_;
95              
96             my @cases = @{ $self->cases };
97             if (@{ $self->config->{'tags'}->{'include'} }) {
98             @cases = grep { $_->hasTags(@{ $self->config->{'tags'}->{'include'} }) } @cases;
99             }
100             if (@{ $self->config->{'tags'}->{'exclude'} }) {
101             my @filtered_cases = ();
102             CASE: foreach my $case (@cases) {
103             foreach my $tag (@{ $self->config->{'tags'}->{'exclude'} }) {
104             next CASE if ($case->hasTags($tag));
105             }
106             push @filtered_cases, $case;
107             }
108             @cases = @filtered_cases;
109             }
110             if ($id) {
111             @cases = grep { $_->id eq $id } @cases;
112             }
113             return \@cases;
114             }
115              
116             has fixture_class => (
117             %default_lazy,
118             isa => q{Str},
119             default => sub {
120             my $self = shift;
121             local @INC = @INC;
122             unless (grep $self->fixture_base, @INC) {
123             unshift @INC, $self->fixture_base;
124             }
125             my $filename = $self->filename;
126             my $root = $self->file_root;
127             $filename =~ s#^$root/?##;
128             $filename =~ s/\s+//g;
129             my @path = split('/', $filename);
130             pop @path; # take off the filename
131             unshift @path, split(/::/, $self->fixture_base);
132              
133             while ($#path > -1) {
134             my $class = join('::', @path);
135             print "# Attempting to load fixture class $class\n" if ($self->verbose > 2);
136             eval {
137             load($class);
138             };
139             unless ($@) {
140             return $class;
141             }
142             if ($@ !~ /^Can't locate /) {
143             warn "Error while loading fixture $class: $@\n";
144             }
145             pop @path;
146             }
147             die 'Cannot find a fixture class for "' . $self->filename . '"';
148             }
149             );
150              
151             sub BUILD {
152             my $self = shift;
153             my ($params) = @_;
154              
155             if (!-f $self->filename){
156             die 'Could not find a8n file "' . $self->filename . '"';
157             }
158             }
159              
160             # unimport moose functions and make immutable
161             no Moose;
162             __PACKAGE__->meta->make_immutable();
163             1;
164              
165             =pod
166              
167             =head1 NAME
168              
169             Test::A8N::File - Storytest file object
170              
171             =head1 SYNOPSIS
172              
173             my $file = Test::A8N::File->new({
174             filename => "cases/test1.tc",
175             file_root => $a8n->file_root,
176             fixture_base => $a8n->fixture_base,
177             });
178             $file->run_tests();
179              
180             =head1 DESCRIPTION
181              
182             This class is used to represent and run tests within individual storytest
183             files. For more information, please see L<Test::A8N>.
184              
185             =head1 METHODS
186              
187             =head2 Accessors
188              
189             =over 4
190              
191             =item filename
192              
193             The filename that this object is supposed to represent.
194              
195             =item fixture_base
196              
197             See L<Test::A8N/fixture_base>.
198              
199             =item file_root
200              
201             See L<Test::A8N/file_root>.
202              
203             =item verbose
204              
205             See L<Test::A8N/verbose>.
206              
207             =item testcase_class
208              
209             Used to set the class used to store testcases.
210              
211             Default: L<Test::A8N::TestCase>
212              
213             =back
214              
215             =head2 Object Methods
216              
217             =over 4
218              
219             =item run_tests
220              
221             This iterates over each of the L</cases> and will create a
222             L<Test::FITesque::Test> test runner for test case. If you call this method
223             with a testcase ID, it will only run that one testcase.
224              
225             =item data
226              
227             Returns the raw datastructure of the YAML file.
228              
229             =item cases
230              
231             Returns objects representing each testcase within this test file. Unless
232             L</testcase_class> is overridden, this property returns instances of the
233             L<Test::A8N::TestCase> class.
234              
235             =item fixture_class
236              
237             This locates the fixture class used to run testcases. The resulting class
238             is called whenever a test action needs to be run.
239              
240             If the L</filename> of this test is one or more sub-directories below the
241             L</file_root>, then it will append the directory name to the
242             L</fixture_base>, and will use it as part of the class name. It works its
243             way up the directory hierarchy until it finds a valid Perl class. If no
244             such classes can be found, it will use the value of L</fixture_base>.
245              
246             =back
247              
248             =head1 SEE ALSO
249              
250             L<Test::A8N::TestCase>, L<Test::FITesque::Test>
251              
252             =head1 AUTHORS
253              
254             Michael Nachbaur E<lt>mike@nachbaur.comE<gt>,
255             Scott McWhirter E<lt>konobi@cpan.orgE<gt>
256              
257             =head1 LICENSE
258              
259             This library is free software; you can redistribute it and/or modify
260             it under the same terms as Perl itself, either Perl version 5.8.7 or,
261             at your option, any later version of Perl 5 you may have available.
262              
263             =head1 COPYRIGHT
264              
265             Copyright (C) 2008 Sophos, Plc.
266              
267             =cut