File Coverage

blib/lib/Test/Run/Trap/Obj.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::Run::Trap::Obj;
2              
3 6     6   144755 use strict;
  6         14  
  6         300  
4 6     6   32 use warnings;
  6         12  
  6         186  
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 6     6   7482 use Moose;
  0            
  0            
31              
32             extends('Test::Run::Base::Struct');
33              
34              
35             use Test::More;
36             use Data::Dumper ();
37              
38             use Text::Sprintf::Named;
39              
40             use Test::Trap qw( trap $trap :flow:stderr(systemsafe):stdout(systemsafe):warn );
41              
42             use Test::Run::Obj;
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             my ($self, $name) = @_;
70              
71             my $value = $self->$name();
72              
73             if (($name eq "return") || ($name eq "warn"))
74             {
75             return Data::Dumper->new([$value])->Dump();
76             }
77             else
78             {
79             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             my $self = shift;
93              
94             diag(
95             Text::Sprintf::Named->new(
96             {
97             fmt =>
98             join( "",
99             map { "$_ ===\n{{{{{{\n%($_)s\n}}}}}}\n\n" }
100             (@fields))
101             }
102             )->format({args => { map { my $name = $_;
103             ($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             local $Test::Builder::Level = $Test::Builder::Level + 1;
119              
120             my $self = shift;
121             my ($what, $regex, $name) = @_;
122              
123             if (! Test::More::like($self->$what(), $regex, $name))
124             {
125             $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             local $Test::Builder::Level = $Test::Builder::Level + 1;
138              
139             my $self = shift;
140             my ($what, $regex, $name) = @_;
141              
142             if (! Test::More::unlike($self->$what(), $regex, $name))
143             {
144             $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             local $Test::Builder::Level = $Test::Builder::Level + 1;
157              
158             my $self = shift;
159             my ($what, $expected, $name) = @_;
160              
161             if (! Test::More::is($self->$what(), $expected, $name))
162             {
163             $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             local $Test::Builder::Level = $Test::Builder::Level + 1;
176              
177             my $self = shift;
178             my ($what, $expected, $name) = @_;
179              
180             if (! Test::More::is_deeply($self->$what(), $expected, $name))
181             {
182             $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             my ($class, $args) = @_;
197              
198             my $test_run_class = $args->{class} || "Test::Run::Obj";
199              
200             my $test_run_args = $args->{args};
201              
202             my $run_func = $args->{run_func} || "runtests";
203              
204             my $tester = $test_run_class->new(
205             {@{$test_run_args}},
206             );
207              
208             trap { $tester->$run_func(); };
209              
210             return $class->new({
211             ( map { $_ => $trap->$_() }
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