File Coverage

blib/lib/Assert/Refute/T/Numeric.pm
Criterion Covered Total %
statement 30 30 100.0
branch 15 18 83.3
condition 6 12 50.0
subroutine 9 9 100.0
pod n/a
total 60 69 86.9


line stmt bran cond sub pod time code
1             package Assert::Refute::T::Numeric;
2              
3 2     2   82584 use strict;
  2         14  
  2         49  
4 2     2   10 use warnings;
  2         2  
  2         75  
5             our $VERSION = '0.16';
6              
7             =head1 NAME
8              
9             Assert::Refute::T::Numeric - Numeric tests for Assert::Refute suite.
10              
11             =head1 SYNOPSIS
12              
13             Somewhere in your unit-test:
14              
15             use Test::More;
16             use Assert::Refute::T::Numeric; # must come *after* Test::More
17              
18             is_between 4 * atan2( 1, 1 ), 3.1415, 3.1416, "Pi number as expected";
19              
20             within_delta sqrt(sqrt(sqrt(10)))**8, 10, 1e-9, "floating point round-trip";
21              
22             within_relative 2**20, 1_000_000, 0.1, "10% precision for 1 mbyte";
23              
24             done_testing;
25              
26             Same for production code:
27              
28             use Assert::Refute;
29             use Assert::Refute::T::Numeric;
30              
31             my $rotate = My::Rotation::Matrix->new( ... );
32             try_refute {
33             within_delta $rotate->determinant, 1, 1e-6, "Rotation keeps distance";
34             };
35              
36             my $total = calculate_price();
37             try_refute {
38             is_between $total, 1, 100, "Price within reasonable limits";
39             };
40              
41             =cut
42              
43 2     2   9 use Carp;
  2         4  
  2         99  
44 2     2   12 use Scalar::Util qw(looks_like_number);
  2         2  
  2         91  
45 2     2   368 use parent qw(Exporter);
  2         292  
  2         10  
46              
47 2     2   505 use Assert::Refute::Build;
  2         7159  
  2         766  
48              
49             =head2 is_between $x, $lower, $upper, [$message]
50              
51             Note that $x comes first and I between boundaries.
52              
53             =cut
54              
55             build_refute is_between => sub {
56 7     7   1380 my ($x, $min, $max) = @_;
57              
58 7 50 33     34 croak "Non-numeric boundaries: ".to_scalar($min, 0).",".to_scalar($max, 0)
59             unless looks_like_number $min and looks_like_number $max;
60              
61 7 100       20 return "Not a number: ".to_scalar($x, 0)
62             unless looks_like_number $x;
63              
64 5 100 100     29 return $min <= $x && $x <= $max ? '' : "$x is not in [$min, $max]";
65             }, args => 3, export => 1;
66              
67             =head2 within_delta $x, $expected, $delta, [$message]
68              
69             Test that $x differs from $expected value by no more than $delta.
70              
71             =cut
72              
73             build_refute within_delta => sub {
74 4     4   8391 my ($x, $exp, $delta) = @_;
75              
76 4 50 33     23 croak "Non-numeric boundaries: ".to_scalar($exp, 0)."+-".to_scalar($delta, 0)
77             unless looks_like_number $exp and looks_like_number $delta;
78              
79 4 100       17 return "Not a number: ".to_scalar($x, 0)
80             unless looks_like_number $x;
81              
82 2 100       26 return abs($x - $exp) <= $delta ? '' : "$x is not in [$exp +- $delta]";
83             }, args => 3, export => 1;
84              
85             =head2 within_relative $x, $expected, $delta, [$message]
86              
87             Test that $x differs from $expected value by no more than $expected * $delta.
88              
89             =cut
90              
91             build_refute within_relative => sub {
92 4     4   6775 my ($x, $exp, $delta) = @_;
93              
94 4 50 33     22 croak "Non-numeric boundaries: ".to_scalar($exp, 0)."+-".to_scalar($delta, 0)
95             unless looks_like_number $exp and looks_like_number $delta;
96              
97 4 100       16 return "Not a number: ".to_scalar($x, 0)
98             unless looks_like_number $x;
99              
100 2 100       22 return abs($x - $exp) <= abs($exp * $delta)
101             ? ''
102             : "$x differs from $exp by more than ".$exp*$delta;
103             }, args => 3, export => 1;
104              
105             =head1 SEE ALSO
106              
107             L.
108              
109             =head1 LICENSE AND COPYRIGHT
110              
111             Copyright 2017-2018 Konstantin S. Uvarin. C<< >>
112              
113             This program is free software; you can redistribute it and/or modify it
114             under the terms of the the Artistic License (2.0). You may obtain a
115             copy of the full license at:
116              
117             L
118              
119             =cut
120              
121             1;