Subtest Design - Test-More/test-more GitHub Wiki
This page describes the internals of how subtests work in Test::Builder 1.5.
Overview
From a Test::Builder point of view, a subtest has to do two basic things:
- Set up a new test state isolated from the parent.
- Communicate the result of the subtest back to the parent.
This is accomplished by giving each level of testing it's own EventCoordinator and EventHandler. Communication is accomplished by handing the subtest's History object back to the parent in an event.
This design tries to keep as much of the complexity of subtests away from the EventHandler authors. Ideally all they need to worry about is "how deeply am I nested".
Creating The New Test State
In TB1, all state resided in the Test::Builder object. This made creating an isolated subtest difficult, one had to swap out the guts of the singleton with a new object and restore it later.
In TB1.5, all state resides in the EventCoordinator and EventWatchers (mostly the History object). Test::Builder no longer holds state because other builders may be generating their own events. Creating a fresh state is a matter of making a new event watchers.
The TestState is the user-visible interface to the EventCoordiantor and Watchers. It holds a stack of EventCoordinators, one for each layer of testing. It delegates all user visible methods to the EventCoordinator on top of the stack (the one representing the state of the current level of testing).
When the TestState receives a subtest_start
event it will...
- TestState fills in information about the level of nesting in the
subtest_start
event if it's not set. ** This prevents builders from having to track nesting, but it allows them to override if they really want to. subtest_start
is posted to the EventHandlers.- TestState creates a new EventCoordinator using the same class as the current one.
- The current EventCoordinator gets a subtest handler from each EventHandler.
**
my $subtest_handler = $handler->subtest_handler($subtest_start_event);
** The subtest event is passed in tosubtest_handler
so it can get information about the subtest, like how far tested it is, without having to remember this information. ** The defaultsubtest_handler
returns a new instance of the handler. - The subtest handlers are added to the new EventCoodinator. ** Retain the same ordering.
- The new EventCoordinator is pushed onto the stack. ** TestState now delegates to EventCoordinator.
- Testing continues normally from
test_start
totest_end
.
Communicating Back
Communication back to the parent is accomplished by attaching the subtest's History object to the subtest_end
event.
Once sub-testing is done, a subtest_end
event will be received by TestState. When that happens...
- TestState attaches the current History object to
subtest_end
. - TestState pops the stack of EventCoordiantors.
- TestState asks the current EventCoordinator to post the
subtest_end
event. - Individual event handlers decide what to do with
subtest_end
. ** Example: the TAP formatter will issue a summarizing "ok/not ok" line.