1Fennec(3pm)           User Contributed Perl Documentation          Fennec(3pm)
2
3
4

NAME

6       Fennec - A testers toolbox, and best friend
7

DESCRIPTION

9       Fennec ties together several testing related modules and enhances their
10       functionality in ways you don't get loading them individually. Fennec
11       makes testing easier, and more useful.
12
13   CAVEAT EMPTOR
14       This module is deprecated in favor of Test2::Suite, specifically
15       Test2::Tools::Spec and Test2::Bundle::SpecDeclare.
16

SYNOPSIS

18       There are 2 ways to use Fennec. You can use Fennec directly, or you can
19       use the shiny sugar-coated interface provided by the add-on module
20       Fennec::Declare.
21
22   VANILLA SYNTAX
23       If Devel::Declare and its awesome power of syntax specification scares
24       you, you can always write your Fennec tests in the stone age like
25       this... just don't miss any semicolons.
26
27       t/some_test.t:
28
29           package TEST::SomeTest;
30           use strict;
31           use warnings;
32
33           use Fennec(
34               parallel  => 3,
35               test_sort => 'random',
36           );
37
38           # This is optional, there is a default 'new' if you do not override it.
39           sub new { ... }
40
41           # Test blocks are called as methods on an instance of your test package.
42           tests group_1 => sub {
43               my $self = shift;
44               ok( 1, "1 is true" );
45           };
46
47           test group_2 => (
48               todo => 'This is not ready yet',
49               code => sub {
50                   my $self = shift;
51                   ok( 0, "Not ready" );
52               }
53           );
54
55           # It is important to always end a Fennec test with this function call.
56           done_testing();
57
58   DECLARE SYNTAX
59       Note: In order to use this you MUST install Fennec::Declare which is a
60       separate distribution on cpan. This module is separate because it uses
61       the controversial Devel::Declare module.
62
63       t/some_test.t:
64
65           package TEST::SomeTest;
66           use strict;
67           use warnings;
68
69           use Fennec::Declare(
70               parallel  => 3,
71               test_sort => 'random',
72           );
73
74           # This is optional, there is a default 'new' if you do not override it.
75           sub new { ... }
76
77           # Test blocks are called as methods on an instance of your test package.
78           tests group_1 {
79               # Note: $self is automatically shifted for you.
80               ok( $self, "Got self automatically" );
81           };
82
83           test group_2 ( todo => 'This is not ready yet' ) {
84               # Note: $self is automatically shifted for you.
85               ok( 0, "Not ready" );
86           }
87
88           # It is important to always end a Fennec test with this function call.
89           done_testing;
90

FEATURES

92   PROVIDED DIRECTLY BY FENNEC
93       Forking just works
94           Forking in perl tests that use Test::Builder is perilous at best.
95           Fennec initiates an Fennec::Collector class which sets up
96           Test::Builder to funnel all test results to the main thread for
97           rendering. A result of this is that forking just works.
98
99       Concurrency, test blocks can run in parallel
100           By default all "test" blocks are run in parallel with a cap of 3
101           concurrent processes. The process cap can be set with the
102           "parallel" import argument.
103
104       No need to maintain a test count
105           The test count traditionally was used to ensure your file finished
106           running instead of exiting silently too early. With Test::Builder
107           and friends this has largely been replaced with the done_testing()
108           function typically called at the end of tests. Fennec shares this
109           concept, but takes it further, you MUST call done_testing() at the
110           end of your test files. This is safer because it can be used to
111           ensure your test script ran completely.
112
113       Can be decoupled from Test::Builder
114           Fennec is built with the assumption that Test::Builder and tools
115           built from it will be used. However custom Fennec::Collector and
116           Fennec::Runner classes can replace this assumption with any testing
117           framework you want to use.
118
119       Can run specific test blocks, excluding others
120           Have you ever had a huge test that took a long time to run? Have
121           you ever needed to debug a failing test at the end of the file? How
122           many times did you need to sit through tests that didn't matter?
123
124           With Fennec you can specify the "FENNEC_TEST" environment variable
125           with either a line number or test block name. Only tests defined on
126           that line, or with that name will be run.
127
128       Predictability: Rand is always seeded with the date
129           Randomizing the order in which test blocks are run can help find
130           subtle interaction bugs. At the same time if tests are always in
131           random order you cannot reliably reproduce a failure.
132
133           Fennec always seeds rand with the current date. This means that on
134           any given date the test run order will always be the same. However
135           different days test different orders. You can always specify the
136           "FENNEC_SEED" environment variable to override the value used to
137           seed rand.
138
139       Diag output is coupled with test output
140           When you run a Fennec test with a verbose harness (prove -v) the
141           diagnostic output will be coupled with the TAP output. This is done
142           by sending both output to STDOUT. In a non-verbose harness the
143           diagnostics will be sent to STDERR per usual.
144
145       Works with Moose
146           All your test classes are instantiated objects. You can use Moose
147           to define these test classes. But you do not have to, you are not
148           forced to use OOP in your tests.
149
150   PROVIDED BY MODULES LOADED BY FENNEC
151       The 3 most common and useful Test::* modules
152           Test::More, Test::Warn, Test::Exception
153
154       RSPEC support
155           Those familiar with Ruby may already know about the RSPEC testing
156           process. In general you "describe" something that is to be tested,
157           then you define setup and teardown methods ("before_all",
158           "before_each", "after_all", "after_each") and then finally you test
159           "it". See the "EXAMPLES" section or Test::Workflow for more
160           details.
161
162       Test re-ordering, tests can run in random, sorted, or defined order.
163           When you load Fennec you can specify a test order. The default is
164           random. You can also use the order in which they are defined, or
165           sorted (alphabetically) order. If necessary you can pass in a
166           sorting function that takes a list of all test-objects as
167           arguments.
168
169           Provided by Test::Workflow
170
171       Reusable test modules
172           You can write tests in modules using Test::Workflow and then import
173           those tests into Fennec tests. This is useful if you have tests
174           that you want run in several, or even all test files.
175
176           Provided by Test::Workflow
177
178       Incredibly powerful mocking with a simple API
179           You can create classless object instances from a specification on
180           the fly, define new packages, or override existing packages.
181
182           Provided by Mock::Quick
183

DEFAULT IMPORTED MODULES

185       Note: These can be overridden either on import, or by subclassing
186       Fennec.
187
188       Child - Forking for dummies
189           Child is an OO interface to forking that removes all the
190           boilderplate such as checking if the pid changed, and making sure
191           you exit the child process.
192
193       Mock::Quick - Mocking without the eye gouging
194           Mock::Quick is a mocking library that makes mocking easy. In
195           addition it uses a declarative style interface. Unlike most other
196           mocking libraries on CPAN, it does not make people want to gouge
197           their eyes out and curl up in the fetal position.
198
199       Test::Workflow - RSPEC for perl.
200           Test::Workflow is a testing library written specifically for
201           Fennec. This library provides RSPEC workflow functions and
202           structure. It can be useful on its own, but combined with Fennec it
203           gets concurrency.
204
205       Test::More
206           Tried and True testing module that everyone uses.
207
208       Test::Warn
209           Test::Warn - Test code that issues warnings.
210
211       Test::Exception
212           Test::Exception - Test code that throws exceptions
213

IMPORT ARGUMENTS

215       base => 'Some::Base'
216           Load the specified module and make it the base class for your test
217           class.
218
219       class => 'What::To::Test'
220           Used to specify the name of the package your test file is
221           validating. When this parameter is specified 3 things are done for
222           you: The class is automatically loaded, the $CLASS variable is
223           imported and contains the module name, and the class() subroutine
224           is defined and returns the name.
225
226               use Fennec class => 'Foo::Bar';
227
228               ok( $INC{'Foo/Bar.pm'}, "Loaded 'Foo::Bar'" );
229               is( $CLASS, 'Foo::Bar', "We have \$CLASS" );
230               is( class(), 'Foo::Bar', "We have class()" );
231
232               tests method => sub {
233                   my $self = shift;
234                   is( $self->class(), 'Foo::Bar', "We have class() method" );
235               };
236
237               done_testing;
238
239       parallel => $PROC_LIMIT
240           How many test blocks can be run in parallel. Default is 3. Set to 1
241           to fork for each test, but only run one at a time. Set to 0 to
242           prevent forking.
243
244           You can also set this using the $FENNEC_PARALLEL environment
245           variable.
246
247       debug => 1
248           Enable tracking debugging information. At the end of the Fennec run
249           it will present you with a CSV temp file. This file lists all
250           blocks that are run, and mocks that are made in sequence from top
251           to bottom. The actions are split into columns by PID. This is
252           usedul when debugging potential race-conditions when using parallel
253           testing.
254
255           Example:
256
257               26150,26151,26152,26153,26154
258               0 26150 BLOCK 54->78 child: outer_wrap, , , , ,
259                ,1 26151 BLOCK 47->52 test: class_store, , , ,
260               0 26150 MOCK Foo => (outer), , , , ,
261               0 26150 BLOCK 58->61 before_all: ba, , , , ,
262                , ,2 26152 MOCK Foo => (outer), , ,
263                , ,2 26152 BLOCK 63->66 before_each: be, , ,
264                , ,2 26152 BLOCK 68->72 test: the_check, , ,
265                , , ,3 26153 BLOCK 16->31 test: object, ,
266                , , , ,4 26154 BLOCK 33->45 test: class,
267
268           You can use this in a spreadsheet program, or use this command to
269           look at it in a more friendly way.
270
271               column -s, -t < '/path/to/tempfile' | less -#2 -S
272
273       collector_class => 'Fennec::Collector::TB::TempFiles'
274           Specify which collector to use. Defaults to a Test::Builder based
275           collector that uses temp files to funnel tests from child procs to
276           the parent.
277
278           You generally won't need to specify this, unless you use a test
279           infrastructure that is neither TAP nore Test::Builder based.
280
281       runner_class => 'Fennec::Runner'
282           Specify the runner class. You probably don't need this.
283
284       runner_params => { ... }
285           Lets you specify arguments used when Fennec::Runner is initialized.
286
287       skip_without => [ 'Need::This', 'And::This' ]
288           Tell Fennec to skip the test file if any of the specified modules
289           are missing.
290
291       test_sort => $SORT
292           Options: 'random', 'sorted', 'ordered', or a code block.
293
294           Code block accepts a list of Test::Workflow::Test objects.
295
296       utils => [ 'Test::Foo', ... ]
297           Load these modules instead of the default list.
298
299           If you need to specify import arguments for any specific util
300           class, you can use the class name as the key with an arrayref
301           containing the arguments.
302
303               use Fennec(
304                   utils          => [ 'Some::Module' ],
305                   'Some::Module' => [ arg => $val, ... ],
306               );
307
308       with_tests => [ 'Reusable::Tests', 'Common::Tests' ]
309           Load these modules that have reusable tests. Reusable tests are
310           tests that are common to multiple test files.
311
312       seed => '...'
313           Set the random seed to be used. Defaults to current date, can be
314           overridden by the FENNEC_SEED environment variable.
315

ENVIRONMENT VARIABLES

317       FENNEC_SEED
318           Can be used to set a specific random seed
319
320       FENNEC_TEST
321           Can be used to tell Fennec to only run specific tests (can be given
322           a line number or a block name).
323
324       FENNEC_DEBUG
325           When true internal debugging is turned on.
326

EXPORTED FUNCTIONS

328   FROM FENNEC
329       done_testing()
330       done_testing(sub { ... })
331           Should be called at the end of your test file to kick off the RSPEC
332           tests.  Always returns 1, so you can use it as the last statement
333           of your module. You must only ever call this once per test file.
334
335           Never put tests below the done_testing call. If you want tests to
336           run AFTER the RSPEC workflow completes, you can pass done_testing a
337           coderef with the tests.
338
339               done_testing( sub {
340                   ok( 1, "This runs after the RSPEC workflow" );
341               });
342
343   FROM Test::Workflow
344       See Test::Workflow or "EXAMPLES" for more details.
345
346       with_tests 'Module::Name';
347           Import tests from a module
348
349       tests $name => sub { ... };
350       tests $name => ( %params );
351       it $name => sub { ... };
352       it $name => ( %params );
353           Define a test block
354
355       describe $name => sub { ... };
356           Describe a set of tests (group tests and setup/teardown functions)
357
358       case $name => sub { ... };
359           Used to run a set of tests against multiple conditions
360
361       before_all $name => sub { ... };
362           Setup, run once before any tests in the describe scope run.
363
364       before_case $name => sub { ... };
365           Setup, run before any case blocks are run.
366
367       before_each $name => sub { ... };
368       after_case $name => sub { ... };
369           Setup, run once per test, just before it runs. Both run after the
370           case block (if there is one).
371
372       around_each $name => sub { ... };
373           Setup and/or teardown.
374
375       after_each $name => sub { ... };
376           Teardown, run once per test, after it finishes.
377
378       after_all $name => sub { ... };
379           Teardown, run once, after all tests in the describe scope complete.
380
381   FROM Mock::Quick
382       See Mock::Quick or "EXAMPLES" for more details.
383
384       my $control = qclass $CLASS => ( %PARAMS, %OVERRIDES );
385       my $control = qtakeover $CLASS => ( %PARAMS, %OVERRIDES );
386       my $control = qimplement $CLASS => ( %PARAMS, %OVERRIDES );
387       my $control = qcontrol $CLASS => ( %PARAMS, %OVERRIDES );
388           Used to define, takeover, or override parts of other packages.
389
390       my $obj = qobj( %PARAMS );
391       my ( $obj, $control ) = qobjc( %PARAMS );
392       my $obj = qstrict( %PARAMS );
393       my ( $obj, $control ) = qstrictc( %PARAMS );
394           Define an object specification, quickly.
395
396       my $clear = qclear();
397           Used to clear a field in a quick object.
398
399       my $meth = qmeth { ... };
400       my $meth = qmeth( sub { ... } );
401           Used to define a method for a quick object.
402
403   OTHER
404       See Test::More, Test::Warn, and Test::Exception
405

EXAMPLES

407       Examples can be the best form of documentation.
408
409   SIMPLE
410       VANILLA SYNTAX
411
412       t/simple.t
413
414           use strict;
415           use warnings;
416
417           use Fennec;
418
419           use_ok 'Data::Dumper';
420
421           tests dumper => sub {
422               my $VAR1;
423               is_deeply(
424                   eval Dumper({ a => 1 }),
425                   { a => 1 },
426                   "Serialize and De-Serialize"
427               );
428           };
429
430           tests future => (
431               todo => "Not ready yet",
432               code => sub {
433                   ok( 0, "I still have to write these" );
434               },
435           );
436
437           done_testing;
438
439       DECLARE SYNTAX
440
441       t/simple.t
442
443           use strict;
444           use warnings;
445
446           use Fennec::Declare;
447
448           use_ok 'Data::Dumper';
449
450           tests dumper {
451               my $VAR1;
452               is_deeply(
453                   eval Dumper({ a => 1 }),
454                   { a => 1 },
455                   "Serialize and De-Serialize"
456               );
457
458               is(
459                   eval { no strict; Dumper( { a => 1 } ) },
460                   { a => 1 },
461                   "Serialize and De-Serialize"
462               );
463           }
464
465           tests future( todo => "Not ready yet" ) {
466               ok( 0, "I still have to write these" );
467           }
468
469           done_testing;
470
471   RUN TESTS UNDER DIFFERENT CONDITIONS
472       This example shows 4 conditions ($letter as 'a', 'b', 'c', and 'd'). It
473       also has 2 test blocks, one that verifies $letter is a letter, the
474       other verifies it is lowercase. Each test block will be run once for
475       each condition, 2*4=8, so in total 8 tests will be run.
476
477       VANILLA
478
479       sample.t:
480
481           use strict;
482           use warnings;
483
484           use Fennec;
485
486           my $letter;
487           case a => sub { $letter = 'a' };
488           case b => sub { $letter = 'b' };
489           case c => sub { $letter = 'c' };
490           case d => sub { $letter = 'd' };
491
492           tests is_letter => sub {
493               like( $letter, qr/^[a-z]$/i, "Got a letter" );
494           };
495
496           tests is_lowercase => sub {
497               is( $letter, lc( $letter ), "Letter is lowercase" );
498           };
499
500           done_testing;
501
502       OBJECT ORIENTED
503
504       sample.t
505
506           use strict;
507           use warnings;
508
509           use Fennec;
510
511           sub letter {
512               my $self = shift;
513               ( $self->{letter} ) = @_ if @_;
514               return $self->{letter};
515           }
516
517           describe letters => sub {
518               case a => sub { shift->letter('a') };
519               case b => sub { shift->letter('b') };
520               case c => sub { shift->letter('c') };
521               case d => sub { shift->letter('d') };
522
523               tests is_letter => sub {
524                   my $self = shift;
525                   like( $self->letter, qr/^[a-z]$/i, "Got a letter" );
526               };
527
528               tests is_lowercase => sub {
529                   my $self = shift;
530                   is( $self->letter, lc( $self->letter ), "Letter is lowercase" );
531               };
532           };
533
534           done_testing;
535
536       DECLARE
537
538       Note: no need to shift $self, it is done for you!
539
540       sample.t
541
542           use strict;
543           use warnings;
544
545           use Fennec::Declare;
546
547           sub letter {
548               my $self = shift;
549               ( $self->{letter} ) = @_ if @_;
550               return $self->{letter};
551           }
552
553           describe letters {
554               case a { $self->letter('a') }
555
556               case b { $self->letter('b') }
557
558               case c { $self->letter('c') }
559
560               case d { $self->letter('d') }
561
562               tests is_letter {
563                   like( $self->letter, qr/^[a-z]$/i, "Got a letter" );
564               }
565
566               tests is_lowercase {
567                   is( $self->letter, lc( $self->letter ), "Letter is lowercase" );
568               }
569           }
570
571           done_testing;
572
573   MOCKING
574       See Mock::Quick for more details
575
576       OBJECT ON THE FLY
577
578           my $obj = qobj(
579               foo => 'foo',
580               bar => qmeth { 'bar' },
581               baz => sub { 'baz' },
582           );
583
584           is( $obj->foo, 'foo' );
585           is( $obj->bar, 'bar' );
586           is( ref $obj->baz, 'CODE', "baz is a method that returns a coderef" );
587
588           # All methods autovivify as read/write accessors:
589           lives_ok { $obj->blah( 'x' ) };
590
591           # use qstrict() to make an object that does not autovivify accessors.
592
593       SCOPE OF MOCKS IN FENNEC
594
595       With vanilla Mock::Quick a mock is destroyed when the control object is
596       destroyed.
597
598           my $control = qtakeover Foo => (blah => 'blah');
599           is( Foo->blah, 'blah', "got mock" );
600           $control = undef;
601           ok( !Foo->can('blah'), "Mock destroyed" );
602
603           # WITHOUT FENNEC This issues a warning, the $control object is ignored so
604           # the mock is destroyed before it can be used.
605           qtakover Foo => (blah => 'blah');
606           ok( !Foo->can('blah'), "Mock destroyed before it could be used" );
607
608       With the workflow support provided by Fennec, you can omit the control
609       object and let the mock be scoped implicitly.
610
611           tests implicit_mock_scope => sub {
612               my $self = shift;
613               can_ok( $self, 'QINTERCEPT' );
614               qtakeover Foo => (blah => sub { 'blah' });
615               is( Foo->blah, 'blah', "Mock not auto-destroyed" );
616           };
617
618           describe detailed_implicit_mock_scope => sub {
619               qtakeover Foo => ( outer => 'outer' );
620               ok( !Foo->can( 'outer' ), "No Leak" );
621
622               before_all ba => sub {
623                   qtakeover Foo => ( ba => 'ba' );
624                   can_ok( 'Foo', qw/outer ba/ );
625               };
626
627               before_each be => sub {
628                   qtakeover Foo => ( be => 'be' );
629                   can_ok( 'Foo', qw/outer ba be/ );
630               };
631
632               tests the_check => sub {
633                   qtakeover Foo => ( inner => 'inner' );
634
635                   can_ok( 'Foo', qw/outer ba be inner/ );
636               };
637
638               ok( !Foo->can( 'outer' ), "No Leak" );
639               ok( !Foo->can( 'ba' ), "No Leak" );
640               ok( !Foo->can( 'be' ), "No Leak" );
641               ok( !Foo->can( 'inner' ), "No Leak" );
642           };
643
644       TAKEOVER AN EXISTING CLASS
645
646           require Some::Class;
647           my $control = qtakeover 'Some::Class' => (
648               # Override some methods:
649               foo => sub { 'foo' },
650               bar => sub { 'bar' },
651
652               # For methods that return a simple value you don't actually need to
653               # wrap them in a sub.
654               baz => 'bat',
655           );
656
657           is( Some::Class->foo, 'foo' );
658           is( Some::Class->bar, 'bar' );
659
660           # Use the control object to make another override
661           $control->override( foo => 'FOO' );
662           is( Some::Class->foo, 'FOO' );
663
664           # Original class is restored when $control falls out of scope.
665           $control = undef;
666
667       MOCK A CLASS INSTEAD OF LOADING THE REAL ONE
668
669       This will prevent the real class from loading if code tries to
670       "require" or "use" it. However when the control object falls out of
671       scope you will be able to load the real one again.
672
673           my $control = qimplement 'Some::Class' => (
674               my_method => sub { ... }
675               simple    => 'foo',
676           );
677
678       MOCK AN ANONYMOUS CLASS
679
680           my $control = qclass(
681               -with_new => 1, # Make a constructor for us
682               method => sub { ... },
683               simple => 'foo',
684           );
685
686           my $obj = $control->package->new;
687
688   REUSABLE TEST LIBRARIES
689       This is a test library that verifies your test file uses strict in the
690       first 3 lines.  You can also pass "with_tests => [ 'Some::Test::Lib' ]"
691       as an import argument to Fennec. This matters because you can subclass
692       Fennec to always include this library.
693
694       t/test.t
695
696           use strict;
697           use warnings;
698           use Fennec;
699
700           with_tests 'Some::Test::Lib';
701
702           done_testing;
703
704       lib/Some/Test/Lib.pm
705
706           package Some::Test::Lib;
707           use Test::Workflow;
708           use Test::More;
709           use Scalar::Util qw/blessed/;
710
711           tests check_use_strict => sub {
712               my $self  = shift;
713               my $class = blessed $self;
714
715               my $file = $class;
716               $file =~ s{::}{/}g;
717               $file .= '.pm';
718
719               my $full = $INC{$file};
720               ok( -e $full, "Found path and filename for $class" );
721               open( my $fh, '<', $full ) || die $!;
722               my $found = 0;
723
724               for ( 1 .. 3 ) {
725                   $found = <$fh> =~ m/^\s*use strict;\s*$/;
726                   last if $found;
727               }
728               close($fh);
729               ok( $found, "'use strict;' is in the first 3 lines of the test file" );
730           }
731
732           1;
733
734   POST TESTS
735       You cannot put any tests under done_testing() Doing so will cause
736       problems.  However you can put tests IN done_testing.
737
738           use strict;
739           use warnings;
740
741           use Fennec;
742
743           my $foo = 1;
744
745           is( $foo, 1, "foo is 1" );
746
747           done_testing(
748               sub {
749                   is( $foo, 1, "foo is still 1" );
750               }
751           );
752
753   RSPEC
754       The following test will produce output similar to the following. Keep
755       in mind that the concurrent nature of Fennec means that the lines for
756       each process may appear out of order relative to lines from other
757       processes. Lines for any given process will always be in the correct
758       order though.
759
760       Spacing has been added, and process output has been grouped together,
761       except for the main process to demonstrate that after_all really does
762       come last.
763
764           # PID          OUTPUT
765           #---------------------------------------------
766           7253 describe runs long before everything else
767           7253 before_all runs first
768
769           7254 case runs between before_all and before_each
770           7254 before_each runs just before tests
771           7254 tests run in the middle
772           7254 after_each runs just after tests
773
774           7255 before_each runs just before tests
775           7255 This test inherits the before and after blocks from the parent describe.
776           7255 after_each runs just after tests
777
778           7253 after_all runs last.
779
780       sample.t
781
782           use strict;
783           use warnings;
784
785           use Fennec;
786
787           describe order => sub {
788               print "$$ describe runs long before everything else\n";
789
790               before_all setup_a => sub {
791                   print "$$ before_all runs first\n";
792               };
793
794               case a_case => sub {
795                   print "$$ case runs between before_all and before_each\n";
796               };
797
798               before_each setup_b => sub {
799                   print "$$ before_each runs just before tests\n";
800               };
801
802               tests a_test => sub {
803                   print "$$ tests run in the middle\n";
804               };
805
806               after_each teardown_b => sub {
807                   print "$$ after_each runs just after tests\n";
808               };
809
810               after_all teardown_a => sub {
811                   print "$$ after_all runs last.\n";
812               };
813
814               describe nested => sub {
815                   tests b_test => sub {
816                       print "$$ This test inherits the before/after/case blocks from the parent describe.\n";
817                   };
818               };
819           };
820
821           done_testing;
822

MANUAL

824       The manual can be found here: Fennec::Manual it is a sort of Nexus for
825       documentation, including this document.
826

VIM INTEGRATION

828       Insert this into your .vimrc file to bind the F8 key to running the
829       test block directly under your cursor. You can be on any line of the
830       test block (except in some cases the first or last line.
831
832           function! RunFennecLine()
833               let cur_line = line(".")
834               exe "!FENNEC_TEST='" . cur_line . "' prove -v -I lib %"
835           endfunction
836
837           " Go to command mode, save the file, run the current test
838           :map <F8> <ESC>:w<cr>:call RunFennecLine()<cr>
839           :imap <F8> <ESC>:w<cr>:call RunFennecLine()<cr>
840

RUNNING FENNEC TEST FILES IN PARALLEL

842       The best option is to use prove with the -j flag.
843
844       Note: The following is no longer a recommended practice, it is however
845       still supported
846
847       You can also create a custom runner using a single .t file to run all
848       your Fennec tests. This has caveats though, such as not knowing which
849       test file had problems without checking the failure messages.
850
851       This will find all *.ft and/or *.pm modules under the t/ directory. It
852       will load and run any found. These will be run in parallel
853
854       t/runner.t
855           #!/usr/bin/perl
856           use strict;
857           use warnings;
858
859           # Paths are optional, if none are specified it defaults to 't/'
860           use Fennec::Finder( 't/' );
861
862           # The next lines are optional, if you have no custom configuration to apply
863           # you can jump right to 'done_testing'.
864
865           # Get the runner (singleton)
866           my $runner = Fennec::Finder->new;
867           $runner->parallel( 3 );
868
869           # You must call this.
870           run();
871

AUTHORS

873       Chad Granum exodist7@gmail.com
874
876       Copyright (C) 2013 Chad Granum
877
878       Fennec is free software; Standard perl license (GPL and Artistic).
879
880       Fennec is distributed in the hope that it will be useful, but WITHOUT
881       ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
882       FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
883
884
885
886perl v5.38.0                      2023-07-20                       Fennec(3pm)
Impressum