1Fennec(3) User Contributed Perl Documentation Fennec(3)
2
3
4
6 Fennec - A testers toolbox, and best friend
7
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
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
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
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
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
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
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
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
824 The manual can be found here: Fennec::Manual it is a sort of Nexus for
825 documentation, including this document.
826
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
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
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.36.0 2023-01-20 Fennec(3)