File Coverage

lib/Generic/Assertions.pm
Criterion Covered Total %
statement 92 95 96.8
branch 31 34 91.1
condition 5 5 100.0
subroutine 25 25 100.0
pod 1 2 50.0
total 154 161 95.6


line stmt bran cond sub pod time code
1 7     7   120008 use 5.006;
  7         20  
  7         238  
2 7     7   27 use strict;
  7         8  
  7         172  
3 7     7   33 use warnings;
  7         7  
  7         379  
4              
5             package Generic::Assertions;
6              
7             our $VERSION = '0.001000'; # TRIAL
8              
9             # ABSTRACT: A Generic Assertion checking class
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 7     7   39 use Carp qw( croak carp );
  7         7  
  7         6476  
14              
15             sub new {
16 50     50 1 60339 my ( $class, @args ) = @_;
17 50 100 100     197 if ( @args % 2 == 1 and not ref $args[0] ) {
18 2         245 croak '->new() expects even number of arguments or a hash reference, got ' . scalar @args . ' argument(s)';
19             }
20 48         52 my $hash;
21 48 100       100 if ( ref $args[0] ) {
22 5         10 $hash = { args => $args[0] };
23             }
24             else {
25 43         120 $hash = { args => {@args} };
26             }
27 48         94 my $self = bless $hash, $class;
28 48         92 $self->BUILD;
29 43         106 return $self;
30             }
31              
32              
33              
34              
35              
36             sub BUILD {
37 48     48 0 48 my ($self) = @_;
38 48         89 my $tests = $self->_tests;
39 48         76 for my $test ( keys %{$tests} ) {
  48         108  
40 31 100       462 croak 'test ' . $test . ' must be a CodeRef' if not 'CODE' eq ref $tests->{$test};
41             }
42 45         93 my $handlers = $self->_handlers;
43 45         121 for my $handler ( keys %{$handlers} ) {
  45         109  
44 272 100       847 croak 'handler ' . $handler . ' must be a CodeRef' if not 'CODE' eq ref $handlers->{$handler};
45             }
46 43 50       104 croak 'input_transformer must be a CodeRef' if not 'CODE' eq ref $self->_input_transformer;
47 43         65 return;
48             }
49              
50             sub _args {
51 223     223   235 my ($self) = @_;
52 223 50       1184 return $self->{args} if exists $self->{args};
53 0         0 return ( $self->{args} = {} );
54             }
55              
56             sub _tests {
57 76     76   68 my ( $self, ) = @_;
58 76 100       202 return $self->{tests} if exists $self->{tests};
59 48         49 my %tests;
60 48         51 for my $key ( grep { !/\A-/msx } keys %{ $self->_args } ) {
  47         178  
  48         73  
61 27         47 $tests{$key} = $self->_args->{$key};
62             }
63 48 100       84 return ( $self->{tests} = { %tests, %{ $self->_args->{'-tests'} || {} } } );
  48         71  
64             }
65              
66             sub _handlers {
67 83     83   82 my ( $self, ) = @_;
68 83 100       229 return $self->{handlers} if exists $self->{handlers};
69 45 100       42 return ( $self->{handlers} = { %{ $self->_handler_defaults }, %{ $self->_args->{'-handlers'} || {} } } );
  45         67  
  45         83  
70             }
71              
72             sub _handler_defaults {
73             return {
74             test => sub {
75 6     6   7 my ($status) = @_;
76 6         33 return $status;
77             },
78             log => sub {
79 6     6   10 my ( $status, $message, $name, @slurpy ) = @_;
80 6   100     779 carp sprintf 'Assertion < log %s > = %s : %s', $name, ( $status || '0' ), $message;
81 6         297 return $slurpy[0];
82             },
83             should => sub {
84 6     6   8 my ( $status, $message, $name, @slurpy ) = @_;
85 6 100       313 carp "Assertion < should $name > failed: $message" unless $status;
86 6         133 return $slurpy[0];
87             },
88             should_not => sub {
89 6     6   9 my ( $status, $message, $name, @slurpy ) = @_;
90 6 100       278 carp "Assertion < should_not $name > failed: $message" if $status;
91 6         136 return $slurpy[0];
92             },
93             must => sub {
94 6     6   10 my ( $status, $message, $name, @slurpy ) = @_;
95 6 100       279 croak "Assertion < must $name > failed: $message" unless $status;
96 3         9 return $slurpy[0];
97             },
98             must_not => sub {
99 6     6   12 my ( $status, $message, $name, @slurpy ) = @_;
100 6 100       347 croak "Assertion < must_not $name > failed: $message" if $status;
101 3         8 return $slurpy[0];
102             },
103 45     45   626 };
104             }
105              
106             sub _transform_input {
107 24     24   24 my ( $self, $name, @slurpy ) = @_;
108 24         33 return $self->_input_transformer->( $name, @slurpy );
109             }
110              
111             sub _input_transformer {
112 67     67   63 my ( $self, ) = @_;
113 67 100       230 return $self->{input_transformer} if exists $self->{input_transformer};
114 43 100       66 if ( exists $self->_args->{'-input_transformer'} ) {
115 12         14 return ( $self->{input_transformer} = $self->_args->{'-input_transformer'} );
116             }
117 31         50 return ( $self->{input_transformer} = $self->_input_transformer_default );
118             }
119              
120             sub _input_transformer_default {
121 12     12   11 return sub { shift; return @_ };
  12     31   22  
  31         179  
122             }
123              
124             # Dispatch the result of test name $test_name
125             sub _handle { ## no critic (Subroutines::ProhibitManyArgs)
126 36     36   210 my ( $self, $handler_name, $status_code, $message, $test_name, @slurpy ) = @_;
127 36         57 return $self->_handlers->{$handler_name}->( $status_code, $message, $test_name, @slurpy );
128             }
129              
130             # Perform $test_name and return its result
131             sub _test {
132 28     28   42 my ( $self, $test_name, @slurpy ) = @_;
133 28         43 my $tests = $self->_tests;
134 28 50       52 if ( not exists $tests->{$test_name} ) {
135 0         0 croak sprintf q[INVALID ASSERTION %s ( avail: %s )], $test_name, ( join q[,], keys %{$tests} );
  0         0  
136             }
137 28         58 return $tests->{$test_name}->(@slurpy);
138             }
139              
140             # Long form
141             # ->_assert( should => exist => path('./foo'))
142             # ->should( exist => path('./foo'))
143             sub _assert {
144 24     24   33 my ( $self, $handler_name, $test_name, @slurpy ) = @_;
145 24         39 my (@input) = $self->_transform_input( $test_name, @slurpy );
146 24         120 my ( $status, $message ) = $self->_test( $test_name, @input );
147 24         155 return $self->_handle( $handler_name, $status, $message, $test_name, @input );
148             }
149              
150             for my $handler (qw( should must should_not must_not test log )) {
151             my $code = sub {
152 24     24   372 my ( $self, $name, @slurpy ) = @_;
153 24         48 return $self->_assert( $handler, $name, @slurpy );
154             };
155             {
156             ## no critic (TestingAndDebugging::ProhibitNoStrict])
157 7     7   45 no strict 'refs';
  7         10  
  7         385  
158             *{ __PACKAGE__ . q[::] . $handler } = $code;
159             }
160             }
161              
162             1;
163              
164             __END__