File Coverage

blib/lib/Test/Subtest/Attribute.pm
Criterion Covered Total %
statement 43 79 54.4
branch 7 24 29.1
condition 2 31 6.4
subroutine 13 16 81.2
pod 7 8 87.5
total 72 158 45.5


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