File Coverage

blib/lib/Test/Subtest/Attribute.pm
Criterion Covered Total %
statement 60 81 74.0
branch 13 26 50.0
condition 6 31 19.3
subroutine 14 16 87.5
pod 7 8 87.5
total 100 162 61.7


line stmt bran cond sub pod time code
1             package Test::Subtest::Attribute;
2              
3             # ABSTRACT: Declare subtests using subroutine attributes
4              
5 2     2   76705 use 5.006;
  2         15  
6 2     2   12 use strict;
  2         4  
  2         42  
7 2     2   9 use warnings;
  2         12  
  2         56  
8              
9              
10 2     2   1902 use Attribute::Handlers;
  2         8045  
  2         12  
11 2     2   70 use Test::Builder qw();
  2         5  
  2         37  
12              
13 2     2   11 use base qw( Exporter );
  2         3  
  2         714  
14              
15             our @EXPORT_OK = qw(
16             subtests
17             );
18             our $VERSION = '0.04';
19              
20             my @subtests;
21             my $builder;
22             my $unknown_sub_count = 0;
23              
24             sub UNIVERSAL::Subtest : ATTR(CODE) { ## no critic (Capitalization)
25 3     3 0 5066 my ( $package, $symbol, $referent, $attr, $data ) = @_;
26              
27 3         6 my $sub_name;
28 3 50       10 if ( ref $symbol ) {
29 3         7 $sub_name = *{ $symbol }{NAME};
  3         7  
30             }
31              
32 3         7 my @args = ();
33 3 100       9 if ( defined $data ) {
34 2 50       7 @args = ref $data ? @{ $data } : ( $data );
  2         8  
35             }
36              
37 3         8 my ( $name, $append_prepend ) = @args;
38 3   100     15 $append_prepend ||= 'append';
39 3 100 66     14 if ( $sub_name && ! $name ) {
40 1         2 $name = $sub_name;
41 1         6 $name =~ s/ ^ subtest_ //msx;
42             }
43              
44 3         18 my %args = (
45             coderef => $referent,
46             data => $data,
47             name => $name,
48             'package' => $package,
49             sub_name => $sub_name,
50             symbol => $symbol,
51             where => $append_prepend,
52             );
53              
54 3         9 subtests()->add( %args );
55              
56 3         12 return 1;
57 2     2   29 }
  2         6  
  2         12  
58              
59              
60             sub subtests {
61 15     15 1 297186 return __PACKAGE__;
62             }
63              
64              
65              
66             sub add {
67 5     5 1 31 my ( $self, %args ) = @_;
68              
69 5   33     18 $args{name} ||= $args{sub_name};
70 5 50       23 if ( ! $args{name} ) {
71 0         0 $unknown_sub_count++;
72 0         0 $args{name} = '__unknown_subtest' . $unknown_sub_count;
73             }
74              
75             # If we have a subtest with the same name as one that's already in our list,
76             # replace it. This allows derived classes to override the subtests in
77             # parent classes.
78 5         18 foreach my $subtest ( @subtests ) {
79 4 50       15 if ( $subtest->{name} eq $args{name} ) {
80 0         0 $subtest = \%args;
81 0         0 return 1;
82             }
83             }
84              
85 5   50     41 $args{where} ||= 'append';
86 5 100       17 if ( $args{where} eq 'prepend' ) {
87 2         12 unshift @subtests, { %args };
88             }
89             else {
90 3         17 push @subtests, { %args };
91             }
92              
93 5         42 return 1;
94             }
95              
96              
97             sub prepend {
98 1     1 1 5 my ( $self, %args ) = @_;
99              
100 1         10 return subtests()->add( %args, where => 'prepend' );
101             }
102              
103              
104             sub append {
105 1     1 1 11 my ( $self, %args ) = @_;
106              
107 1         13 return subtests()->add( %args, where => 'append' );
108             }
109              
110              
111             sub remove {
112 2     2 1 7 my ( $self, $which ) = @_;
113              
114 2 50       7 return if ! $which;
115              
116 2 100       13 my $field = ref $which ? 'coderef' : 'name';
117 2         6 my @clean = grep { $_->{ $field } ne $which } @subtests;
  3         13  
118 2         5 @subtests = @clean;
119              
120 2         9 return 1;
121             }
122              
123              
124             sub get_all {
125 6     6 1 24 return @subtests;
126             }
127              
128              
129             sub run {
130 0     0 1   my ( $self, %args ) = @_;
131              
132 0   0       $builder ||= $args{builder} || Test::Builder->new();
      0        
133              
134 0           foreach my $subtest ( @subtests ) {
135 0   0       my $invocant = $args{invocant} || $subtest->{package} || 'main';
136 0   0       my $name = $subtest->{name} || '(unknown)';
137 0 0         if ( $args{verbose_names} ) {
138 0   0       my $sub_name = $subtest->{sub_name} || '(unknown sub)';
139 0           my $package_name = $subtest->{package};
140 0 0 0       my $verbose_name = ( $package_name && $package_name ne 'main' )
141             ? "${package_name}::${sub_name}"
142             : $sub_name;
143 0           $name .= " [$verbose_name]";
144             }
145              
146 0           my $subref = $subtest->{coderef};
147 0 0 0       if ( $subtest->{sub_name} && ! $subref ) {
148 0           $subref = $invocant->can( $subtest->{sub_name} );
149             }
150 0 0 0       if ( $subref && ref $subref eq 'CODE' ) {
151 0     0     $builder->subtest( $name, sub { return $invocant->$subref(); } );
  0            
152             }
153             }
154              
155 0           return 1;
156             }
157              
158             1;
159              
160             __END__