File Coverage

blib/lib/Test/Auto.pm
Criterion Covered Total %
statement 33 96 34.3
branch 4 10 40.0
condition n/a
subroutine 9 34 26.4
pod 8 18 44.4
total 54 158 34.1


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