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 11     11   463496 use 5.006;
  11         110  
4 11     11   78 use strict;
  11         23  
  11         276  
5 11     11   62 use warnings;
  11         19  
  11         589  
6             our $VERSION = '0.1501';
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 11     11   82 use Carp;
  11         19  
  11         724  
51 11     11   2918 use parent qw(Exporter);
  11         2119  
  11         67  
52             our @EXPORT = qw(foobar);
53              
54 11     11   3685 use Assert::Refute::Build;
  11         32  
  11         802  
55 11     11   4198 use Assert::Refute::Contract;
  11         31  
  11         4914  
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 14     14   32 my ($block, $rex) = @_;
74              
75 14         26 my $lived = eval {
76 14         41 $block->();
77 4         12 1;
78             };
79              
80 14 100       236 if ($rex) {
81 10         58 $rex = qr/$rex/;
82 10 100       34 return "Block didn't die" if $lived;
83 9 50       24 return "Exception wasn't true" unless $@;
84 9 100       110 return $@ =~ $rex ? '' : "Exception was: $@\nExpected: $rex";
85             } else {
86 4 100       21 return if $lived;
87 1 50       10 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 16     16   41 my ($block, $exp) = @_;
127              
128 16 100       69 $exp = $exp ? [ $exp ] : []
    100          
129             unless ref $exp eq 'ARRAY';
130 16         93 $_ = qr/$_/ for @$exp;
131              
132 16         33 my @warn;
133             {
134 16     14   28 local $SIG{__WARN__} = sub { push @warn, shift };
  16         107  
  14         639  
135 16         52 $block->();
136             };
137              
138 16         459 my $c = $multi_like->apply( \@warn, $exp );
139 16 100       46 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;