File Coverage

blib/lib/Assert/Refute/T/Errors.pm
Criterion Covered Total %
statement 41 41 100.0
branch 16 18 88.8
condition n/a
subroutine 10 10 100.0
pod n/a
total 67 69 97.1


line stmt bran cond sub pod time code
1             package Assert::Refute::T::Errors;
2              
3 10     10   471555 use 5.006;
  10         104  
4 10     10   80 use strict;
  10         27  
  10         296  
5 10     10   57 use warnings;
  10         20  
  10         556  
6             our $VERSION = '0.16';
7              
8             =head1 NAME
9              
10             Assert::Refute::T::Errors - exception and warning check for Assert::Refute suite
11              
12             =head1 SYNOPSIS
13              
14             use Assert::Refute qw(:all);
15             use Assert::Refute::T::Errors;
16              
17             my $c = contract {
18             my $foo = shift;
19             dies_like {
20             $foo->bar;
21             } "Bar requires an argument";
22             dies_like {
23             $foo->bar(1);
24             } '', "Bar works fine with 1";
25             };
26              
27             $c->apply( $my_foo ); # check whether foo lives/dies as expected
28              
29             Ditto with L (although there are more fine-grained L
30             and L):
31              
32             use Test::More;
33             use Assert::Refute::T::Errors; # always *after* Test::More
34              
35             use My::Module;
36              
37             dies_like {
38             My::Module->foo;
39             } qw/foo requires/, "Epmty argument prohibited";
40             dies_like {
41             My::Module->bar;
42             } '', "Works without arguments";
43              
44             =head1 EXPORTED FUNCTIONS
45              
46             All functions below are exported by default.
47              
48             =cut
49              
50 10     10   76 use Carp;
  10         19  
  10         700  
51 10     10   3431 use parent qw(Exporter);
  10         2201  
  10         64  
52             our @EXPORT = qw(foobar);
53              
54 10     10   3926 use Assert::Refute::Build;
  10         25  
  10         670  
55 10     10   4351 use Assert::Refute::Contract;
  10         23  
  10         4240  
56              
57             =head2 dies_like
58              
59             dies_like {
60             # shoddy code here
61             } 'pattern', 'explanation';
62              
63             Check that supplied code throws the expected exception.
64              
65             If pattern is empty, expect the code to live through.
66              
67             Otherwise convert it to regular expression if needed
68             and match C<$@> against it.
69              
70             =cut
71              
72             build_refute dies_like => sub {
73 22     22   57 my ($block, $rex) = @_;
74              
75 22         39 my $lived = eval {
76 22         75 $block->();
77 4         15 1;
78             };
79              
80 22 100       629 if ($rex) {
81 18         95 $rex = qr/$rex/;
82 18 100       59 return "Block didn't die" if $lived;
83 17 50       48 return "Exception wasn't true" unless $@;
84 17 100       211 return $@ =~ $rex ? '' : "Exception was: $@\nExpected: $rex";
85             } else {
86 4 100       24 return if $lived;
87 1 50       7 return $@
88             ? "Exception was: $@\nExpected to live"
89             : Carp::shortmess "Block died"."Expected to live";
90             }
91             }, block => 1, export => 1, args => 1;
92              
93             =head2 warns_like { ... }
94              
95             warns_like {
96             warn "Foo";
97             warn "Bar";
98             } [qr/Foo/, "Bar"], "Human comment";
99              
100             warns_like {
101             # Shoddy code here
102             } '', "No warnings";
103              
104             Check that exactly the specified warnings were emitted by block.
105             A single string or regex value is accepted and converted to 1-element array.
106              
107             An empty array or a false value mean no warnings at all.
108              
109             Note that this block does NOT catch exceptions.
110             This MAY change in the future.
111              
112             =cut
113              
114             # TODO better diagnostic
115             my $multi_like = Assert::Refute::Contract->new( code => sub {
116             my ($self, $got, $exp) = @_;
117              
118             for (my $i = 0; $i < @$got or $i < @$exp; $i++) {
119             defined $exp->[$i]
120             ? $self->like( $got->[$i], $exp->[$i] )
121             : $self->is ( $got->[$i], undef );
122             };
123             }, need_object => 1 );
124              
125             build_refute warns_like => sub {
126 11     11   29 my ($block, $exp) = @_;
127              
128 11 100       45 $exp = $exp ? [ $exp ] : []
    100          
129             unless ref $exp eq 'ARRAY';
130 11         64 $_ = qr/$_/ for @$exp;
131              
132 11         22 my @warn;
133             {
134 11     9   19 local $SIG{__WARN__} = sub { push @warn, shift };
  11         72  
  9         432  
135 11         32 $block->();
136             };
137              
138 11         64 my $c = $multi_like->apply( \@warn, $exp );
139 11 100       30 return $c->is_passing ? '' : $c->get_tap;
140             }, block => 1, args => 1, export => 1;
141              
142             =head1 LICENSE AND COPYRIGHT
143              
144             This module is part of L suite.
145              
146             Copyright 2017-2018 Konstantin S. Uvarin. C<< >>
147              
148             This program is free software; you can redistribute it and/or modify it
149             under the terms of the the Artistic License (2.0). You may obtain a
150             copy of the full license at:
151              
152             L
153              
154             =cut
155              
156             1;