File Coverage

blib/lib/Scientist.pm
Criterion Covered Total %
statement 49 49 100.0
branch 16 16 100.0
condition n/a
subroutine 11 11 100.0
pod 4 4 100.0
total 80 80 100.0


line stmt bran cond sub pod time code
1             ## no critic (Miscellanea::ProhibitUnrestrictedNoCritic, ValuesAndExpressions::ProhibitVersionStrings)
2             package Scientist;
3              
4 9     9   1993433 use Moo;
  9         84207  
  9         57  
5 9     9   16873 use Test2::Compare v0.0.121 qw/compare strict_convert/;
  9         7929  
  9         651  
6 9     9   770 use Test2::Compare::Delta;
  9         118127  
  9         384  
7 9     9   68 use Time::HiRes qw/time/;
  9         21  
  9         92  
8 9     9   7101 use Types::Standard qw/Bool Str CodeRef HashRef/;
  9         1392121  
  9         124  
9              
10             our $VERSION = '0.014'; # VERSION
11              
12             # ABSTRACT: Perl module inspired by https://github.com/github/scientist
13             # https://github.com/lancew/Scientist
14              
15             has 'context' => (
16             is => 'rw',
17             isa => HashRef,
18             );
19              
20             has 'enabled' => (
21             is => 'rw',
22             isa => Bool,
23             default => 1,
24             );
25              
26             has 'experiment' => (
27             is => 'ro',
28             isa => Str,
29             builder => 'name',
30             );
31              
32             has 'use' => (
33             is => 'rw',
34             isa => CodeRef,
35             );
36              
37             has 'result' => (
38             is => 'rw',
39             isa => HashRef,
40             );
41              
42             has 'try' => (
43             is => 'rw',
44             isa => CodeRef,
45             );
46              
47             sub name {
48 13     13 1 1541238 return 'experiment';
49             }
50              
51             sub publish {
52 1009     1009 1 1987 my $self = shift;
53             # Stub publish sub, extend this to enable your own own
54             # unique publishing requirements
55 1009         1792 return;
56             }
57              
58             sub run {
59 1014     1014 1 8030 my $self = shift;
60              
61             # If experiment not enabled just return the control code results.
62 1014 100       29011 return $self->use->() unless $self->enabled;
63              
64 1011         28995 my %result = (
65             context => $self->context,
66             experiment => $self->experiment,
67             );
68              
69 1011         9255 my $wantarray = wantarray;
70              
71 1011         1758 my ( @control, @candidate );
72             my $run_control = sub {
73 1011     1011   2568 my $start = time;
74 1011 100       24625 @control = $wantarray ? $self->use->() : scalar $self->use->();
75 1010         12152 $result{control}{duration} = time - $start;
76 1011         5745 };
77              
78             my $run_candidate = sub {
79 1011     1011   3388 my $start = time;
80             @candidate = $wantarray
81 1         11 ? eval { $self->try->() }
82 1011 100       2579 : eval { scalar $self->try->() };
  1010         24123  
83 1011         13259 $result{candidate}{duration} = time - $start;
84 1011         4062 };
85              
86 1011 100       2968 if ( rand > 0.5 ) {
87 491         1233 $run_control->();
88 491         992 $run_candidate->();
89             }
90             else {
91 520         1298 $run_candidate->();
92 520         1021 $run_control->();
93             }
94              
95 1010         4250 my $delta = compare(\@candidate, \@control, \&strict_convert);
96 1010 100       418835 my $diag = $delta ? $delta->table->as_string : '';
97              
98 1010         24651 $result{matched} = $diag eq '';
99 1010         2492 $result{mismatched} = $diag ne '';
100              
101             $result{observation} = {
102 1010 100       5643 candidate => $wantarray ? @candidate : $candidate[0],
    100          
103             control => $wantarray ? @control : $control[0],
104             diagnostic => $diag,
105             };
106              
107 1010         36667 $self->result( \%result );
108 1010         39937 $self->publish;
109              
110 1009 100       12267 return $wantarray ? @control : $control[0];
111             }
112              
113             # Use better column header names in the observation diagnostic table.
114             sub BUILD {
115 15     15 1 589750 Test2::Compare::Delta->set_column_alias(GOT => 'CONTROL');
116 15         186 Test2::Compare::Delta->set_column_alias(CHECK => 'CANDIDATE');
117 15         165 return;
118             }
119              
120             1;
121              
122             =head1 LICENSE
123              
124             This software is Copyright (c) 2016 by Lance Wicks.
125              
126             This is free software, licensed under:
127              
128             The MIT (X11) License
129              
130             The MIT License
131              
132             Permission is hereby granted, free of charge, to any person
133             obtaining a copy of this software and associated
134             documentation files (the "Software"), to deal in the Software
135             without restriction, including without limitation the rights to
136             use, copy, modify, merge, publish, distribute, sublicense,
137             and/or sell copies of the Software, and to permit persons to
138             whom the Software is furnished to do so, subject to the
139             following conditions:
140              
141             The above copyright notice and this permission notice shall
142             be included in all copies or substantial portions of the
143             Software.
144              
145             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
146             WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
147             INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
148             MERCHANTABILITY, FITNESS FOR A PARTICULAR
149             PURPOSE AND NONINFRINGEMENT. IN NO EVENT
150             SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
151             LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152             LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
153             TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
154             CONNECTION WITH THE SOFTWARE OR THE USE OR
155             OTHER DEALINGS IN THE SOFTWARE.