File Coverage

blib/lib/Dist/Zilla/Plugin/Test/Inline.pm
Criterion Covered Total %
statement 50 50 100.0
branch 1 2 50.0
condition n/a
subroutine 14 14 100.0
pod 1 1 100.0
total 66 67 98.5


line stmt bran cond sub pod time code
1 1     1   1650521 use strict;
  1         3  
  1         65  
2             package Dist::Zilla::Plugin::Test::Inline;
3             # ABSTRACT: Create test files from inline tests in POD sections
4             # VERSION
5             $Dist::Zilla::Plugin::Test::Inline::VERSION = '0.011003';
6             #pod =head1 SYNOPSIS
7             #pod
8             #pod In your C<dist.ini>:
9             #pod
10             #pod [Test::Inline]
11             #pod
12             #pod In your module:
13             #pod
14             #pod # My/AddressRange.pm
15             #pod
16             #pod =begin testing
17             #pod
18             #pod use Test::Exception;
19             #pod dies_ok {
20             #pod My::AddressRange->list_from_range('10.2.3.A', '10.2.3.5')
21             #pod } "list_from_range() complains about invalid address";
22             #pod
23             #pod =end testing
24             #pod
25             #pod =cut
26             #pod
27             #pod sub list_from_range {
28             #pod # ...
29             #pod }
30             #pod
31             #pod This will result in a file C<t/inline-tests/my_addressrange.t> in your distribution.
32             #pod
33             #pod =head1 DESCRIPTION
34             #pod
35             #pod This plugin integrates L<Test::Inline> into C<Dist::Zilla>.
36             #pod
37             #pod It scans all modules for inline tests in POD sections that are embedded between
38             #pod the keywords
39             #pod
40             #pod =begin testing
41             #pod ...
42             #pod =end testing
43             #pod
44             #pod and exports them into C<t/inline-tests/*.t> files when C<Dist::Zilla> builds
45             #pod your module. Multiple of these test sections may be specified within one file.
46             #pod
47             #pod Please note that this plugin (in contrast to pure L<Test::Inline>) can also
48             #pod handle L<Moops>-like class and role definitions.
49             #pod
50             #pod =head1 ACKNOWLEDGEMENTS
51             #pod
52             #pod The code of this Dist::Zilla file gatherer plugin is mainly taken from
53             #pod L<https://github.com/moose/moose/blob/master/inc/ExtractInlineTests.pm>.
54             #pod
55             #pod =for :list
56             #pod * Dave Rolsky <autarch@urth.org>, who basically wrote all this but left the honor of making a plugin of it to me ;-)
57             #pod
58             #pod =cut
59              
60 1     1   5 use Moose;
  1         1  
  1         10  
61             with 'Dist::Zilla::Role::FileGatherer';
62              
63 1     1   5147 use File::Basename qw( basename );
  1         6  
  1         67  
64 1     1   4 use File::Spec;
  1         2  
  1         36  
65 1     1   4 use File::Temp qw( tempdir );
  1         1  
  1         59  
66 1     1   623 use File::Find::Rule;
  1         6420  
  1         6  
67 1     1   589 use Test::Inline;
  1         30082  
  1         35  
68 1     1   467 use Dist::Zilla::File::InMemory;
  1         63261  
  1         214  
69              
70             #pod =method gather_files
71             #pod
72             #pod Required by role L<Dist::Zilla::Role::FileGatherer>.
73             #pod
74             #pod Searches for inline test code in POD sections using L<Test::Inline>, creates
75             #pod in-memory test files and passes them to L<Dist::Zilla>.
76             #pod
77             #pod =cut
78             sub gather_files {
79 1     1 1 712450 my $self = shift;
80 1         3 my $arg = shift;
81              
82 1         4 $self->log("extracting inline tests from POD sections");
83              
84             # give Test::Inline our own input and output handlers
85 1         281 my $inline = Test::Inline->new(
86             verbose => 0,
87             ExtractHandler => 'Dist::Zilla::Plugin::Test::Inline::Extract',
88             OutputHandler => Dist::Zilla::Plugin::Test::Inline::Output->new($self),
89             );
90              
91 1         122 $inline->add_all;
92 1         419 $inline->save;
93             }
94              
95             #
96             # Used to connect Test::Inline to Dist::Zilla
97             # (write generated test code into in-memory files)
98             #
99             {
100             package Dist::Zilla::Plugin::Test::Inline::Output;
101             $Dist::Zilla::Plugin::Test::Inline::Output::VERSION = '0.011003';
102             sub new {
103 1     1   2 my $class = shift;
104 1         2 my $dzil = shift;
105              
106 1         13 return bless { dzil => $dzil }, $class;
107             }
108              
109             sub write {
110 1     1   391 my $self = shift;
111 1         2 my $name = shift;
112 1         2 my $content = shift;
113              
114 1         43 $self->{dzil}->add_file(
115             Dist::Zilla::File::InMemory->new(
116             name => "t/inline-tests/$name",
117             content => $content,
118             )
119             );
120              
121 1         638 return 1;
122             }
123             }
124             #
125             # Taken from https://github.com/moose/Moose/blob/master/inc/MyInline.pm
126             #
127             {
128             package Dist::Zilla::Plugin::Test::Inline::Extract;
129             $Dist::Zilla::Plugin::Test::Inline::Extract::VERSION = '0.011003';
130 1     1   8 use parent 'Test::Inline::Extract';
  1         2  
  1         7  
131            
132             # Extract code specifically marked for testing
133             our $search = qr/
134             (?:^|\n) # After the beginning of the string, or a newline
135             ( # ... start capturing
136             # EITHER
137             package\s+ # A package
138             [^\W\d]\w*(?:(?:\'|::)[^\W\d]\w*)* # ... with a name
139             \s*; # And a statement terminator
140             | # OR
141             class\s+ # A class
142             [^\W\d]\w*(?:(?:\'|::)[^\W\d]\w*)* # ... with a name
143             ($|\s+|\s*{) # And some spaces or an opening bracket
144             | # OR
145             role\s+ # A role
146             [^\W\d]\w*(?:(?:\'|::)[^\W\d]\w*)* # ... with a name
147             ($|\s+|\s*{) # And some spaces or an opening bracket
148             | # OR
149             =for[ \t]+example[ \t]+begin\n # ... when we find a =for example begin
150             .*? # ... and keep capturing
151             \n=for[ \t]+example[ \t]+end\s*? # ... until the =for example end
152             (?:\n|$) # ... at the end of file or a newline
153             | # OR
154             =begin[ \t]+(?:test|testing)\b # ... when we find a =begin test or testing
155             .*? # ... and keep capturing
156             \n=end[ \t]+(?:test|testing)\s*? # ... until an =end tag
157             (?:\n|$) # ... at the end of file or a newline
158             ) # ... and stop capturing
159             /isx;
160            
161             sub _elements {
162 1     1   6573 my $self = shift;
163 1         3 my @elements = ();
164 1         16 while ( $self->{source} =~ m/$search/go ) {
165 2         3 my $element = $1;
166             # rename "role" or "class" to "package" so Test::Inline understands
167 2         4 $element =~ s/^(role|class)(\s+)/package$2/;
168 2         6 $element =~ s/\n\s*$//;
169 2         18 push @elements, $element;
170             }
171            
172 1 50   2   7 (List::Util::first { /^=/ } @elements) ? \@elements : '';
  2         9  
173             }
174            
175             }
176              
177              
178             1;
179              
180             __END__
181              
182             =pod
183              
184             =head1 NAME
185              
186             Dist::Zilla::Plugin::Test::Inline - Create test files from inline tests in POD sections
187              
188             =head1 VERSION
189              
190             version 0.011003
191              
192             =head1 SYNOPSIS
193              
194             In your C<dist.ini>:
195              
196             [Test::Inline]
197              
198             In your module:
199              
200             # My/AddressRange.pm
201              
202             =begin testing
203              
204             use Test::Exception;
205             dies_ok {
206             My::AddressRange->list_from_range('10.2.3.A', '10.2.3.5')
207             } "list_from_range() complains about invalid address";
208              
209             =end testing
210            
211             =cut
212            
213             sub list_from_range {
214             # ...
215             }
216              
217             This will result in a file C<t/inline-tests/my_addressrange.t> in your distribution.
218              
219             =head1 DESCRIPTION
220              
221             This plugin integrates L<Test::Inline> into C<Dist::Zilla>.
222              
223             It scans all modules for inline tests in POD sections that are embedded between
224             the keywords
225              
226             =begin testing
227             ...
228             =end testing
229              
230             and exports them into C<t/inline-tests/*.t> files when C<Dist::Zilla> builds
231             your module. Multiple of these test sections may be specified within one file.
232              
233             Please note that this plugin (in contrast to pure L<Test::Inline>) can also
234             handle L<Moops>-like class and role definitions.
235              
236             =head1 METHODS
237              
238             =head2 gather_files
239              
240             Required by role L<Dist::Zilla::Role::FileGatherer>.
241              
242             Searches for inline test code in POD sections using L<Test::Inline>, creates
243             in-memory test files and passes them to L<Dist::Zilla>.
244              
245             =head1 ACKNOWLEDGEMENTS
246              
247             The code of this Dist::Zilla file gatherer plugin is mainly taken from
248             L<https://github.com/moose/moose/blob/master/inc/ExtractInlineTests.pm>.
249              
250             =over 4
251              
252             =item *
253              
254             Dave Rolsky <autarch@urth.org>, who basically wrote all this but left the honor of making a plugin of it to me ;-)
255              
256             =back
257              
258             =head1 AUTHOR
259              
260             Jens Berthold <jens.berthold@jebecs.de>
261              
262             =head1 COPYRIGHT AND LICENSE
263              
264             This software is copyright (c) 2015 by Jens Berthold.
265              
266             This is free software; you can redistribute it and/or modify it under
267             the same terms as the Perl 5 programming language system itself.
268              
269             =cut