File Coverage

blib/lib/Test/Run/Trap/Obj.pm
Criterion Covered Total %
statement 50 64 78.1
branch 4 12 33.3
condition 4 7 57.1
subroutine 14 16 87.5
pod 6 6 100.0
total 78 105 74.2


line stmt bran cond sub pod time code
1             package Test::Run::Trap::Obj;
2              
3 7     7   113244 use strict;
  7         15  
  7         177  
4 7     7   36 use warnings;
  7         15  
  7         222  
5              
6             =head1 NAME
7              
8             Test::Run::Trap::Obj - wrapper around Test::Trap for trapping errors.
9              
10             =head1 SYNPOSIS
11              
12             my $got = Test::Run::Trap::Obj->trap_run({
13             args => [test_files => ["t/sample-tests/simple"]]
14             });
15              
16             $got->field_like("stdout", qr/All tests successful/,
17             "Everything is OK."
18             );
19              
20             =head1 DESCRIPTION
21              
22             This class implements a wrapper around L<Test::Trap>. When an
23             assertion files, the diagnostics prints all the relevant and trapped
24             fields for easy debugging.
25              
26             =head1 METHODS
27              
28             =cut
29              
30 7     7   4945 use Moose;
  7         2919441  
  7         48  
31              
32             extends('Test::Run::Base::Struct');
33              
34              
35 7     7   47786 use Test::More;
  7         13  
  7         77  
36 7     7   10291 use Data::Dumper ();
  7         53108  
  7         202  
37              
38 7     7   4477 use Text::Sprintf::Named;
  7         6989  
  7         367  
39              
40 7     7   5835 use Test::Trap qw( trap $trap :flow:stderr(systemsafe):stdout(systemsafe):warn );
  7         337100  
  7         49  
41              
42 7     7   5304 use Test::Run::Obj;
  7         31  
  7         96  
43              
44             my @fields = qw(
45             die
46             exit
47             leaveby
48             return
49             stderr
50             stdout
51             wantarray
52             warn
53             run_func
54             );
55              
56              
57             has 'die' => (is => "rw", isa => "Any");
58             has 'exit' => (is => "rw", isa => "Any");
59             has 'leaveby' => (is => "rw", isa => "Str");
60             has 'return' => (is => "rw", isa => "Any");
61             has 'stderr' => (is => "rw", isa => "Str");
62             has 'stdout' => (is => "rw", isa => "Str");
63             has 'wantarray' => (is => "rw", isa => "Bool");
64             has 'warn' => (is => "rw", isa => "Any");
65             has 'run_func' => (is => "rw", isa => "CodeRef");
66              
67             sub _stringify_value
68             {
69 0     0   0 my ($self, $name) = @_;
70              
71 0         0 my $value = $self->$name();
72              
73 0 0 0     0 if (($name eq "return") || ($name eq "warn"))
74             {
75 0         0 return Data::Dumper->new([$value])->Dump();
76             }
77             else
78             {
79 0 0       0 return (defined($value) ? $value : "");
80             }
81             }
82              
83             =head2 $trapper->diag_all()
84              
85             Calls L<Test::More>'s diag() with all the trapped fields, like stdout,
86             stderr, etc.
87              
88             =cut
89              
90             sub diag_all
91             {
92 0     0 1 0 my $self = shift;
93              
94             diag(
95             Text::Sprintf::Named->new(
96             {
97             fmt =>
98             join( "",
99 0         0 map { "$_ ===\n{{{{{{\n%($_)s\n}}}}}}\n\n" }
100             (@fields))
101             }
102 0         0 )->format({args => { map { my $name = $_;
  0         0  
103 0         0 ($name => $self->_stringify_value($name)) }
104             @fields
105             }})
106             );
107             }
108              
109             =head2 $trapper->field_like($what, $regex, $message)
110              
111             A wrapper for L<Test::More>'s like(), that also emits more diagnostics
112             on failure.
113              
114             =cut
115              
116             sub field_like
117             {
118 25     25 1 28744 local $Test::Builder::Level = $Test::Builder::Level + 1;
119              
120 25         64 my $self = shift;
121 25         194 my ($what, $regex, $name) = @_;
122              
123 25 50       1091 if (! Test::More::like($self->$what(), $regex, $name))
124             {
125 0         0 $self->diag_all();
126             }
127             }
128              
129             =head2 $trapper->field_unlike($what, $regex, $msg)
130              
131             A wrapper for unlike().
132              
133             =cut
134              
135             sub field_unlike
136             {
137 1     1 1 1947 local $Test::Builder::Level = $Test::Builder::Level + 1;
138              
139 1         3 my $self = shift;
140 1         5 my ($what, $regex, $name) = @_;
141              
142 1 50       40 if (! Test::More::unlike($self->$what(), $regex, $name))
143             {
144 0         0 $self->diag_all();
145             }
146             }
147              
148             =head2 $trapper->field_is($what, $expected, $msg)
149              
150             A wrapper for is().
151              
152             =cut
153              
154             sub field_is
155             {
156 4     4 1 6331 local $Test::Builder::Level = $Test::Builder::Level + 1;
157              
158 4         8 my $self = shift;
159 4         21 my ($what, $expected, $name) = @_;
160              
161 4 50       162 if (! Test::More::is($self->$what(), $expected, $name))
162             {
163 0         0 $self->diag_all();
164             }
165             }
166              
167             =head2 $trapper->field_is_deeply($what, $expected, $msg)
168              
169             A wrapper for is_deeply().
170              
171             =cut
172              
173             sub field_is_deeply
174             {
175 1     1 1 1662 local $Test::Builder::Level = $Test::Builder::Level + 1;
176              
177 1         7 my $self = shift;
178 1         9 my ($what, $expected, $name) = @_;
179              
180 1 50       51 if (! Test::More::is_deeply($self->$what(), $expected, $name))
181             {
182 0         0 $self->diag_all();
183             }
184             }
185              
186              
187             =head2 my $got = Test::Run::Trap::Obj->trap_run({class => $class, args => \@args, run_func => $func})
188              
189             Runs C<$class->$func()> with the arguments @args placed into a hash-ref,
190             traps the results and returns a results object.
191              
192             =cut
193              
194             sub trap_run
195             {
196 25     25 1 1283655 my ($class, $args) = @_;
197              
198 25   100     223 my $test_run_class = $args->{class} || "Test::Run::Obj";
199              
200 25         63 my $test_run_args = $args->{args};
201              
202 25   100     165 my $run_func = $args->{run_func} || "runtests";
203              
204             my $tester = $test_run_class->new(
205 25         65 {@{$test_run_args}},
  25         306  
206             );
207              
208 25     25   2129 trap { $tester->$run_func(); };
  25         46267  
209              
210             return $class->new({
211 25         606433 ( map { $_ => $trap->$_() }
  200         1624  
212             (qw(stdout stderr die leaveby exit return warn wantarray)))
213             });
214             }
215              
216             1;
217              
218             =head1 AUTHOR
219              
220             Shlomi Fish, L<http://www.shlomifish.org/>.
221              
222             =head1 LICENSE
223              
224             This file is licensed under the MIT X11 License:
225              
226             http://www.opensource.org/licenses/mit-license.php
227              
228             =head1 SEE ALSO
229              
230             L<Test::Trap> , L<Test::More> .
231              
232             =cut