File Coverage

blib/lib/Assert/Refute/T/Tester.pm
Criterion Covered Total %
statement 41 41 100.0
branch 15 16 93.7
condition 9 12 75.0
subroutine 9 9 100.0
pod n/a
total 74 78 94.8


line stmt bran cond sub pod time code
1             package Assert::Refute::T::Tester;
2              
3 1     1   423 use strict;
  1         2  
  1         24  
4 1     1   4 use warnings;
  1         1  
  1         37  
5             our $VERSION = '0.16';
6              
7             =head1 NAME
8              
9             Assert::Refute::T::Tester - test the test conditions themselves
10              
11             =head1 DESCRIPTION
12              
13             This module is inspired by L.
14             While C is a good way to quickly determine
15             whether a test condition holds any water, a more detailed
16             inspection is desirable.
17              
18             B<[EXPERIMENTAL]> This module is under active development and
19             its interface may change in the future.
20              
21             =head1 SYNOPSIS
22              
23             use Test::More;
24             use Assert::Refute::T::Tester;
25              
26             use My::Refute::Module qw(check_this check_that);
27              
28             my $report = try_refute {
29             check_this(...); # pass
30             check_that(...); # fail
31             };
32              
33             test_test
34             $report->get_result_details(0),
35             { diag => [] },
36             "No premature output";
37              
38             test_test
39             $report->get_result_details(1),
40             { ok => 1 },
41             "Passing test";
42              
43             test_test
44             $report->get_result_details(2),
45             { ok => 0, diag => [ qr/foo/, qr/bar/ ] },
46             "Failing test";
47              
48             =head1 EXPORT
49              
50             The following functions are exported by default:
51              
52             =cut
53              
54 1     1   4 use Carp;
  1         1  
  1         47  
55 1     1   4 use parent qw(Exporter);
  1         2  
  1         4  
56 1     1   38 use Assert::Refute::Build;
  1         2  
  1         477  
57              
58             =head2 test_test
59              
60             test_test \%result_details, \%spec, "Message";
61              
62             Result details come from L.
63              
64             The exact format MAY change in the future, but this test should keep working.
65              
66             %spec may include:
67              
68             =over
69              
70             =item * C - whether the test passed or not.
71              
72             =item * C - test name (without the number)
73             Can be exact string or regular expression.
74              
75             =item * C - an array of exact strings or regular expressions.
76             Each line of output will be matched against exactly one expectation.
77              
78             Output produced by C is ignored.
79              
80             =back
81              
82             =cut
83              
84             build_refute test_test => \&_test_test, manual => 1, args => 2, export => 1;
85              
86             my %allow;
87             $allow{$_}++ for qw( ok name diag );
88             sub _test_test {
89 20     20   34 my ($self, $hash, $spec, $external_name) = @_;
90              
91 20 50 33     73 croak "Usage: test_test( \%test_result, \%spec, [ \"message\" ] )"
92             if (ref $hash ne 'HASH' or ref $spec ne 'HASH');
93              
94 20         45 my @extra = grep { !$allow{$_} } keys %$spec;
  25         63  
95 20 100       250 croak "test_test(): Unknown fields (@extra) in spec"
96             if @extra;
97              
98 19         22 my $ok = $spec->{ok};
99 19         27 my $name = $spec->{name};
100 19         26 my $diag = $spec->{diag};
101              
102 19 100 100     168 croak "test_test(): diag() must be an array of strings and/or regular expressions"
103             if $diag and ref $diag ne 'ARRAY';
104              
105 18   50     54 $external_name ||= "Assert::Refute contract entry as expected";
106              
107             $self->subcontract( $external_name => sub {
108 18     18   19 my $rep = shift;
109              
110 18 100       35 if (defined $ok) {
111 8 100 100     47 $rep->refute( ($ok xor $hash->{ok}), "test ".($ok?"passed":"failed"));
112             };
113              
114 18 100       28 if (defined $name) {
115 4         12 _like_or_ok( $rep, $hash->{name}, $name, "Test name is $name" );
116             };
117              
118 18 100       34 if (defined $diag) {
119 10         18 _lines_like( $rep, $hash->{diag}, $diag, "Diagnostics" );
120             };
121 18         83 } );
122             };
123              
124             sub _lines_like {
125 10     10   24 my ($rep, $got, $exp, $message) = @_;
126              
127 10         26 foreach (0 .. @$exp-1) {
128 10         32 _like_or_ok( $rep, $got->[$_], $exp->[$_],
129             "$message: Line $_ matches ".to_scalar( $exp->[$_] ) );
130             };
131 10         38 $rep->is( scalar @$got, scalar @$exp,
132             "$message: Exactly ".(scalar @$exp)." lines present" );
133             };
134              
135             sub _like_or_ok {
136 14     14   28 my ($rep, $got, $exp, $msg) = @_;
137              
138 14 100       30 if (ref $exp eq 'Regexp') {
139 11         28 $rep->like( $got, $exp, $msg );
140             } else {
141 3         7 $rep->is( $got, $exp, $msg );
142             };
143             };
144              
145             =head1 LICENSE AND COPYRIGHT
146              
147             This module is part of L suite.
148              
149             Copyright 2017-2018 Konstantin S. Uvarin. C<< >>
150              
151             This program is free software; you can redistribute it and/or modify it
152             under the terms of the the Artistic License (2.0). You may obtain a
153             copy of the full license at:
154              
155             L
156              
157             =cut
158              
159             1;