File Coverage

blib/lib/Test/Auto.pm
Criterion Covered Total %
statement 33 94 35.1
branch 4 10 40.0
condition n/a
subroutine 9 33 27.2
pod 8 17 47.0
total 54 154 35.0


line stmt bran cond sub pod time code
1             package Test::Auto;
2              
3 1     1   454 use 5.018;
  1         2  
4              
5 1     1   4 use strict;
  1         1  
  1         15  
6 1     1   4 use warnings;
  1         2  
  1         20  
7              
8 1     1   4 use base 'Venus::Test';
  1         1  
  1         495  
9              
10 1     1   103983 use Test::More;
  1         2  
  1         7  
11              
12             # VERSION
13              
14             our $VERSION = '0.13';
15              
16             # AUTHORITY
17              
18             our $AUTHORITY = 'cpan:AWNCORP';
19              
20             # IMPORT
21              
22             sub import {
23 8     8   115562 my ($self, @args) = @_;
24              
25 8         19 my $from = caller;
26              
27 1     1   319 no strict 'refs';
  1         2  
  1         947  
28              
29 8 100       10 if (!*{"${from}::test"}{"CODE"}) {
  8         42  
30 1         2 *{"${from}::test"} = \&testauto;
  1         3  
31             }
32              
33 8 100       18 if (!*{"${from}::testauto"}{"CODE"}) {
  8         25  
34 1         2 *{"${from}::testauto"} = \&testauto;
  1         2  
35             }
36              
37 8         230 return $self;
38             }
39              
40             # BUILDERS
41              
42             sub build_self {
43 9     9 0 6238 my ($self, $data) = @_;
44              
45 9         37 $self->Venus::Data::build_self($data);
46              
47 9         462 for my $item (grep !$self->count({name => $_}), qw(
48             name abstract synopsis description
49             ))
50             {
51 0         0 $self->throw->error({message => "Failed to find =$item"});
52             }
53              
54 9         71246 return $self;
55             };
56              
57             # FUNCTIONS (< 0.13 API)
58              
59             sub testauto {
60 2     2 0 125 __PACKAGE__->new($_[0]);
61             }
62              
63             # METHODS (< 0.13 API)
64              
65             sub standard {
66 0     0 0   my ($self) = @_;
67              
68             # approximating the v1 API subtests
69 0           $self->package;
70 0           $self->document;
71 0 0         $self->libraries if $self->count({name => 'libraries'});
72 0 0         $self->inherits if $self->count({name => 'inherits'});
73 0           $self->attributes;
74 0           $self->methods;
75 0           $self->routines;
76 0           $self->functions;
77 0           $self->types;
78              
79 0           return $self;
80             }
81              
82             sub package {
83 0     0 0   my ($self) = @_;
84              
85             # approximating the v1 API subtests
86 0           $self->for('name');
87              
88 0           return $self;
89             }
90              
91             sub plugin {
92 0     0 0   my ($self, $name) = @_;
93              
94             subtest "testing plugin ($name)", sub {
95 0     0     plan skip_all => "plugins are no longer supported";
96 0           };
97              
98 0           return $self;
99             }
100              
101             sub libraries {
102 0     0 1   my ($self) = @_;
103              
104             # approximating the v1 API subtests
105 0           $self->for('libraries');
106              
107 0           return $self;
108             }
109              
110             sub inherits {
111 0     0 1   my ($self) = @_;
112              
113             # approximating the v1 API subtests
114 0           $self->for('inherits');
115              
116 0           return $self;
117             }
118              
119             sub document {
120 0     0 0   my ($self) = @_;
121              
122             # approximating the v1 API subtests
123             subtest "testing document", sub {
124 0     0     ok $self->data($_), "pod $_" for qw(
125             name
126             abstract
127             synopsis
128             abstract
129             description
130             );
131 0           };
132              
133 0           return $self;
134             }
135              
136             sub attributes {
137 0     0 1   my ($self) = @_;
138              
139             subtest "testing attributes", sub {
140 0     0     plan skip_all => "< 0.12-style attributes testing is no longer supported";
141 0           };
142              
143 0           return $self;
144             }
145              
146             sub methods {
147 0     0 1   my ($self) = @_;
148              
149             subtest "testing methods", sub {
150 0     0     plan skip_all => "< 0.12-style methods testing is no longer supported";
151 0           };
152              
153 0           return $self;
154             }
155              
156             sub routines {
157 0     0 1   my ($self) = @_;
158              
159             subtest "testing routines", sub {
160 0     0     plan skip_all => "< 0.12-style routines testing is no longer supported";
161 0           };
162              
163 0           return $self;
164             }
165              
166             sub functions {
167 0     0 1   my ($self) = @_;
168              
169             subtest "testing functions", sub {
170 0     0     plan skip_all => "< 0.12-style functions testing is no longer supported";
171 0           };
172              
173 0           return $self;
174             }
175              
176             sub types {
177 0     0 0   my ($self) = @_;
178              
179             subtest "testing types", sub {
180 0     0     plan skip_all => "< 0.12-style types testing is no longer supported";
181 0           };
182              
183 0           return $self;
184             }
185              
186             sub synopsis {
187 0     0 1   my ($self, @args) = @_;
188              
189 0           $self->for('synopsis', @args);
190              
191 0           return $self;
192             }
193              
194             sub scenario {
195              
196 0     0 0   my ($self) = @_;
197              
198             subtest "testing scenario", sub {
199 0     0     plan skip_all => "< 0.12-style scenario testing is no longer supported";
200 0           };
201              
202 0           return $self;
203             }
204              
205             sub example {
206 0     0 1   my ($self, $id, $name, $type, $code) = @_;
207              
208 0 0   0     $self->for('example', ($id < 0 ? -$id : $id), $name, (sub{ $code->(@_); 1 }));
  0            
  0            
209              
210 0           return $self;
211             }
212              
213       0 0   sub tests {
214             # See "plugin", e.g. $self->plugin($name)->tests;
215             }
216              
217             1;
218              
219              
220             =head1 NAME
221              
222             Test::Auto - Test Automation
223              
224             =cut
225              
226             =head1 ABSTRACT
227              
228             Test Automation for Perl 5
229              
230             =cut
231              
232             =head1 VERSION
233              
234             0.13
235              
236             =cut
237              
238             =head1 SYNOPSIS
239              
240             package main;
241              
242             use Test::Auto;
243             use Test::More;
244              
245             my $test = Test::Auto->new(
246             't/Test_Auto.t'
247             );
248              
249             # =synopsis
250             #
251             # use Path::Find 'path';
252             #
253             # my $path = path; # get path using cwd
254             #
255             # =cut
256              
257             # $test->for('synopsis', sub {
258             # my ($tryable) = @_;
259             # ok my $result = $tryable->result;
260             #
261             # # more test for the synopsis ...
262             #
263             # $result
264             # });
265              
266             # ...
267              
268             # $test->render('lib/Path/Find.pod');
269              
270             # done_testing
271              
272             =cut
273              
274             =head1 DESCRIPTION
275              
276             This package aims to provide, a standard for documenting Perl 5 software
277             projects, a framework writing tests, test automation, and documentation
278             generation.
279              
280             =head1 AUTOMATION
281              
282             # ...
283              
284             $test->for('name');
285              
286             This framework provides a set of automated subtests based on the package
287             specification, but not everything can be automated so it also provides you with
288             powerful hooks into the framework for manual testing.
289              
290             # ...
291              
292             $test->for('synopsis', sub {
293             my ($tryable) = @_;
294              
295             ok my $result = $tryable->result, 'result ok';
296              
297             # must return truthy to cont
298             $result;
299             });
300              
301             The code examples documented can be automatically evaluated (evaled) and
302             returned using a callback you provide for further testing. Because the code
303             examples are returned as L objects this makes capturing and testing
304             exceptions simple, for example:
305              
306             # ...
307              
308             $test->for('synopsis', sub {
309             my ($tryable) = @_;
310              
311             # catch exception thrown by the synopsis
312             $tryable->catch('Path::Find::Error', sub {
313             return $_[0];
314             });
315              
316             # test the exception
317             ok my $result = $tryable->result, 'result ok';
318             ok $result->isa('Path::Find::Error'), 'exception caught';
319              
320             # must return truthy to cont
321             $result;
322             });
323              
324             Additionally, another manual testing hook (with some automation) is the
325             C method. This hook evaluates (evals) a given example and returns the
326             result as a L object. The first argument is the example ID (or
327             number), for example:
328              
329             # ...
330              
331             $test->for('example', 1, 'children', sub {
332             my ($tryable) = @_;
333              
334             ok my $result = $tryable->result, 'result ok';
335              
336             # must return truthy to cont
337             $result;
338             });
339              
340             Finally, the lesser-used but useful manual testing hook is the C
341             method. This hook evaluates (evals) a documented feature and returns the result
342             as a L object, for example:
343              
344             # ...
345              
346             $test->for('feature', 'export-path-make', sub {
347             my ($tryable) = @_;
348              
349             ok my $result = $tryable->result, 'result ok';
350              
351             # must return truthy to cont
352             $result;
353             });
354              
355             The test automation and documentation generation enabled through this framework
356             makes it easy to maintain source/test/documentation parity. This also increases
357             reusability and reduces the need for complicated state and test setup.
358              
359             =head1 SPECIFICATION
360              
361             # Since 0.13
362              
363             # [required]
364              
365             =name
366             =abstract
367             =tagline
368             =includes
369             =synopsis
370             =description
371              
372             # [optional]
373              
374             =libraries
375             =inherits
376             =integrates
377              
378             # [repeatable; optional]
379              
380             =feature $name
381             =example $name
382              
383             # [repeatable; optional]
384              
385             =attribute $name
386             =signature $name
387             =example-$number $name # [repeatable]
388              
389             # [repeatable; optional]
390              
391             =method $name
392             =signature $name
393             =example-$number $name # [repeatable]
394              
395             # [repeatable; optional]
396              
397             =function $name
398             =signature $name
399             =example-$number $name # [repeatable]
400              
401             # [repeatable; optional]
402              
403             =routine $name
404             =signature $name
405             =example-$number $name # [repeatable]
406              
407             The specification is designed to accommodate typical package declarations. It
408             is used by the parser to provide the content used in test automation and
409             document generation. B When code blocks are evaluated I<"redefined">
410             warnings are now automatically disabled.
411              
412             =head2 name
413              
414             =name
415              
416             Path::Find
417              
418             =cut
419              
420             The C block should contain the package name. This is tested for
421             loadability.
422              
423             =head2 tagline
424              
425             =tagline
426              
427             Path Finder
428              
429             =cut
430              
431             The C block should contain a tagline for the package. This is optional
432             but if present is concatenated with the C during POD generation.
433              
434             =head2 abstract
435              
436             =abstract
437              
438             Find Paths using Heuristics
439              
440             =cut
441              
442             The C block should contain a subtitle describing the package. This is
443             tested for existence.
444              
445             =head2 includes
446              
447             =includes
448              
449             function: path
450             method: children
451             method: siblings
452             method: new
453              
454             =cut
455              
456             The C block should contain a list of C, C, and/or
457             C names in the format of C<$type: $name>. Empty lines are ignored.
458             This is tested for existence. Each function, method, and/or routine is tested
459             to be documented properly, i.e. has the requisite counterparts (e.g. signature
460             and at least one example block). Also, the package must recognize that each
461             exists.
462              
463             =head2 synopsis
464              
465             =synopsis
466              
467             use Path::Find 'path';
468              
469             my $path = path; # get path using cwd
470              
471             =cut
472              
473             The C block should contain the normative usage of the package. This
474             is tested for existence. This block should be written in a way that allows it
475             to be evaled successfully and should return a value.
476              
477             =head2 description
478              
479             =description
480              
481             interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit duis
482             tristique sollicitudin nibh sit amet
483              
484             =cut
485              
486             The C block should contain a thorough explanation of the purpose
487             of the package. This is tested for existence.
488              
489             =head2 libraries
490              
491             =libraries
492              
493             Types::Standard
494             Types::TypeTiny
495              
496             =cut
497              
498             The C block should contain a list of packages, each of which is
499             itself a L. These packages are tested for loadability, and to
500             ensure they are type library classes.
501              
502             =head2 inherits
503              
504             =inherits
505              
506             Path::Tiny
507              
508             =cut
509              
510             The C block should contain a list of parent packages. These packages
511             are tested for loadability.
512              
513             =head2 integrates
514              
515             =integrates
516              
517             Path::Find::Upable
518             Path::Find::Downable
519              
520             =cut
521              
522             The C block should contain a list of packages that are involved in
523             the behavior of the main package. These packages are not automatically tested.
524              
525             =head2 features
526              
527             =feature export-path-make
528              
529             quisque egestas diam in arcu cursus euismod quis viverra nibh
530              
531             =example export-path-make
532              
533             # given: synopsis
534              
535             package main;
536              
537             use Path::Find 'path_make';
538              
539             path_make 'relpath/to/file';
540              
541             =cut
542              
543              
544             There are situation where a package can be configured in different ways,
545             especially where it exists without functions, methods or routines for the
546             purpose of configuring the environment. The feature directive can be used to
547             automate testing and documenting package usages and configurations. Describing
548             a feature requires two blocks, i.e. C and C. The
549             C block should contain a description of the feature and its purpose.
550             The C block must exist when documenting a feature and should contain
551             valid Perl code and return a value. The block may contain a "magic" comment in
552             the form of C or C which if present will
553             include the given code example(s) with the evaluation of the current block.
554             Each feature is tested and must be recognized to exist by the main package.
555              
556             =head2 attributes
557              
558             =attribute cwd
559              
560             quis viverra nibh cras pulvinar mattis nunc sed blandit libero volutpat
561              
562             =signature cwd
563              
564             cwd(Str $path) : (Object)
565              
566             =example-1 cwd
567              
568             # given: synopsis
569              
570             my $cwd = $path->cwd;
571              
572             =example-2 cwd
573              
574             # given: synopsis
575              
576             my $cwd = $path->cwd('/path/to/file');
577              
578             =cut
579              
580             Describing an attribute requires at least three blocks, i.e. C
581             $name>, C, and C. The C block
582             should contain a description of the attribute and its purpose. The C
583             block should contain a routine signature in the form of C<$signature :
584             $return_type>, where C<$signature> is a valid typed signature and
585             C<$return_type> is any valid L expression. The C
586             block is a repeatable block, and at least one block must exist when documenting
587             an attribute. The C block should contain valid Perl code and
588             return a value. The block may contain a "magic" comment in the form of C
589             synopsis> or C which if present will include the
590             given code example(s) with the evaluation of the current block. Each attribute
591             is tested and must be recognized to exist by the main package.
592              
593             =head2 methods
594              
595             =method children
596              
597             quis viverra nibh cras pulvinar mattis nunc sed blandit libero volutpat
598              
599             =signature children
600              
601             children() : [Object]
602              
603             =example-1 children
604              
605             # given: synopsis
606              
607             my $children = $path->children;
608              
609             =example-2 children
610              
611             # given: synopsis
612              
613             my $filtered = $path->children(qr/lib/);
614              
615             =cut
616              
617             Describing a method requires at least three blocks, i.e. C,
618             C, and C. The C block should contain
619             a description of the method and its purpose. The C block should
620             contain a method signature in the form of C<$signature : $return_type>, where
621             C<$signature> is a valid typed signature and C<$return_type> is any valid
622             L expression. The C block is a repeatable block,
623             and at least one block must exist when documenting a method. The
624             C block should contain valid Perl code and return a value. The
625             block may contain a "magic" comment in the form of C or
626             C which if present will include the given code
627             example(s) with the evaluation of the current block. Each method is tested and
628             must be recognized to exist by the main package.
629              
630             =head2 functions
631              
632             =function path
633              
634             lectus quam id leo in vitae turpis massa sed elementum tempus egestas
635              
636             =signature children
637              
638             path() : Object
639              
640             =example-1 path
641              
642             package Test::Path::Find;
643              
644             use Path::Find;
645              
646             my $path = path;
647              
648             =cut
649              
650             Describing a function requires at least three blocks, i.e. C,
651             C, and C. The C block should
652             contain a description of the function and its purpose. The C block
653             should contain a function signature in the form of C<$signature :
654             $return_type>, where C<$signature> is a valid typed signature and
655             C<$return_type> is any valid L expression. The C
656             block is a repeatable block, and at least one block must exist when documenting
657             a function. The C block should contain valid Perl code and
658             return a value. The block may contain a "magic" comment in the form of C
659             synopsis> or C which if present will include the
660             given code example(s) with the evaluation of the current block. Each function
661             is tested and must be recognized to exist by the main package.
662              
663             =head2 routines
664              
665             =routine algorithms
666              
667             sed sed risus pretium quam vulputate dignissim suspendisse in est ante
668              
669             =signature algorithms
670              
671             algorithms() : Object
672              
673             =example-1 algorithms
674              
675             # given: synopsis
676              
677             $path->algorithms
678              
679             =example-2 algorithms
680              
681             package Test::Path::Find;
682              
683             use Path::Find;
684              
685             Path::Find->algorithms;
686              
687             =cut
688              
689             Typically, a Perl subroutine is declared as a function or a method. Rarely, but
690             sometimes necessary, you will need to describe a subroutine where the invocant
691             is either a class or class instance. Describing a routine requires at least
692             three blocks, i.e. C, C, and C
693             $name>. The C block should contain a description of the routine and
694             its purpose. The C block should contain a routine signature in the
695             form of C<$signature : $return_type>, where C<$signature> is a valid typed
696             signature and C<$return_type> is any valid L expression. The
697             C block is a repeatable block, and at least one block must
698             exist when documenting a routine. The C block should contain
699             valid Perl code and return a value. The block may contain a "magic" comment in
700             the form of C or C which if
701             present will include the given code example(s) with the evaluation of the
702             current block. Each routine is tested and must be recognized to exist by the
703             main package.
704              
705             =cut
706              
707             =head1 INHERITS
708              
709             This package inherits behaviors from:
710              
711             L
712              
713             =cut
714              
715             =head1 FUNCTIONS
716              
717             This package provides the following functions:
718              
719             =cut
720              
721             =head2 test
722              
723             test(Str $file) (Auto)
724              
725             The test function takes a file path and returns a L object for use
726             in test automation and documentation rendering. This function is exported
727             automatically unless a routine of the same name already exists in the calling
728             package.
729              
730             I>
731              
732             =over 4
733              
734             =item test example 1
735              
736             # given: synopsis
737              
738             $test = test('t/Test_Auto.t');
739              
740             # =synopsis
741             #
742             # use Path::Find 'path';
743             #
744             # my $path = path; # get path using cwd
745             #
746             # =cut
747              
748             # $test->for('synopsis', sub {
749             # my ($tryable) = @_;
750             # ok my $result = $tryable->result;
751             #
752             # # more test for the synopsis ...
753             #
754             # $result
755             # });
756              
757             # ...
758              
759             # $test->render('lib/Path/Find.pod');
760              
761             # done_testing
762              
763             =back
764              
765             =cut
766              
767             =head1 METHODS
768              
769             This package provides the following methods:
770              
771             =cut
772              
773             =head2 data
774              
775             data(Str $name, Any @args) (Str)
776              
777             The data method attempts to find and return the POD content based on the name
778             provided. If the content cannot be found an exception is raised.
779              
780             I>
781              
782             =over 4
783              
784             =item data example 1
785              
786             # given: synopsis
787              
788             my $data = $test->data('name');
789              
790             # Test::Auto
791              
792             =back
793              
794             =over 4
795              
796             =item data example 2
797              
798             # given: synopsis
799              
800             my $data = $test->data('unknown');
801              
802             # Exception! isa (Test::Auto::Error)
803              
804             =back
805              
806             =cut
807              
808             =head2 for
809              
810             for(Str $name | CodeRef $code, Any @args) (Any)
811              
812             The for method attempts to find the POD content based on the name provided and
813             executes the corresponding predefined test, optionally accepting a callback
814             which, if provided, will be passes a L object containing the
815             POD-driven test. The callback, if provided, must always return a true value.
816             B All automated tests disable the I<"redefine"> class of warnings to
817             prevent warnings when redeclaring packages in examples.
818              
819             I>
820              
821             =over 4
822              
823             =item for example 1
824              
825             # given: synopsis
826              
827             my $data = $test->for('name');
828              
829             # Test::Auto
830              
831             =back
832              
833             =over 4
834              
835             =item for example 2
836              
837             # given: synopsis
838              
839             my $data = $test->for('synosis');
840              
841             # bless({value => 't/Test_Auto.t'}, 'Test::Auto')
842              
843             =back
844              
845             =over 4
846              
847             =item for example 3
848              
849             # given: synopsis
850              
851             my $data = $test->for('example', 1, 'data', sub {
852             my ($tryable) = @_;
853             my $result = $tryable->result;
854             ok length($result) > 1;
855              
856             $result
857             });
858              
859             # Test::Auto
860              
861             =back
862              
863             =cut
864              
865             =head2 render
866              
867             render(Str $file) (Path)
868              
869             The render method renders and writes a valid POD document, and returns a
870             L object representation the POD file specified.
871              
872             I>
873              
874             =over 4
875              
876             =item render example 1
877              
878             # given: synopsis
879              
880             my $path = $test->render('t/Path_Find.pod');
881              
882             # bless({value => 't/Path_Find.pod', 'Venus::Path'})
883              
884             =back
885              
886             =cut
887              
888             =head1 AUTHORS
889              
890             Awncorp, C
891              
892             =cut