Forking in perl tests that use Test::Builder is perilous at best. Fennec initiates an Fennec::Collector class which sets up Test::Builder to funnel all test results to the main thread for rendering. A result of this is that forking just works.

The test count traditionally was used to ensure your file finished running instead of exiting silently too early. With Test::Builder and friends this has largely been replaced with the done_testing() function typically called at the end of tests. Fennec shares this concept, but takes it further, you MUST call done_testing() at the end of your test files. This is safer because it can be used to ensure your test script ran completely.

Fennec is built with the assumption that Test::Builder and tools built from it will be used. However custom Fennec::Collector and Fennec::Runner classes can replace this assumption with any testing framework you want to use.

Randomizing the order in which test blocks are run can help find subtle interaction bugs. At the same time if tests are always in random order you cannot reliably reproduce a failure.

Fennec always seeds rand with the current date. This means that on any given date the test run order will always be the same. However different days test different orders. You can always specify the FENNEC_SEED environment variable to override the value used to seed rand.

When you run a Fennec test with a verbose harness (prove -v) the diagnostic output will be coupled with the TAP output. This is done by sending both output to STDOUT. In a non-verbose harness the diagnostics will be sent to STDERR per usual.

Those familiar with Ruby may already know about the RSPEC testing process. In general you describe something that is to be tested, then you define setup and teardown methods (before_all, before_each, after_all, after_each) and then finally you test it. See the "EXAMPLES" section or Test::Workflow for more details.

When you load Fennec you can specify a test order. The default is random. You can also use the order in which they are defined, or sorted (alphabetically) order. If necessary you can pass in a sorting function that takes a list of all test-objects as arguments.

Mock::Quick is a mocking library that makes mocking easy. In addition it uses a declarative style interface. Unlike most other mocking libraries on CPAN, it does not make people want to gouge their eyes out and curl up in the fetal position.

Test::Workflow is a testing library written specifically for Fennec. This library provides RSPEC workflow functions and structure. It can be useful on its own, but combined with Fennec it gets concurrency.

Used to specify the name of the package your test file is validating. When this parameter is specified 3 things are done for you: The class is automatically loaded, the $CLASS variable is imported and contains the module name, and the class() subroutine is defined and returns the name.

Enable tracking debugging information. At the end of the Fennec run it will present you with a CSV temp file. This file lists all blocks that are run, and mocks that are made in sequence from top to bottom. The actions are split into columns by PID. This is usedul when debugging potential race-conditions when using parallel testing.

This example shows 4 conditions ($letter as 'a', 'b', 'c', and 'd'). It also has 2 test blocks, one that verifies $letter is a letter, the other verifies it is lowercase. Each test block will be run once for each condition, 2*4=8, so in total 8 tests will be run.

This is a test library that verifies your test file uses strict in the first 3 lines. You can also pass with_tests => [ 'Some::Test::Lib' ] as an import argument to Fennec. This matters because you can subclass Fennec to always include this library.

t/test.t

use strict;
use warnings;
use Fennec;
with_tests 'Some::Test::Lib';
done_testing;

The following test will produce output similar to the following. Keep in mind that the concurrent nature of Fennec means that the lines for each process may appear out of order relative to lines from other processes. Lines for any given process will always be in the correct order though.

Spacing has been added, and process output has been grouped together, except for the main process to demonstrate that after_all really does come last.

# PID OUTPUT
#---------------------------------------------
7253 describe runs long before everything else
7253 before_all runs first
7254 Case runs between before_all and before_each
7254 before_each runs just before tests
7254 tests run in the middle
7254 after_each runs just after tests
7255 before_each runs just before tests
7255 This test inherits the before and after blocks from the parent describe.
7255 after_each runs just after tests
7253 after_all runs last.

Note: The following is no longer a recommended practice, it is however still supported

You can also create a custom runner using a single .t file to run all your Fennec tests. This has caveats though, such as not knowing which test file had problems without checking the failure messages.

This will find all *.ft and/or *.pm modules under the t/ directory. It will load and run any found. These will be run in parallel

t/runner.t #!/usr/bin/perl use strict; use warnings;

# Paths are optional, if none are specified it defaults to 't/'
use Fennec::Finder( 't/' );
# The next lines are optional, if you have no custom configuration to apply
# you can jump right to 'done_testing'.
# Get the runner (singleton)
my $runner = Fennec::Finder->new;
$runner->parallel( 3 );
# You must call this.
run();

Fennec is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.