Test2:...Preload(3pm)
π Test2::Harness::Runner::Preload π
okay bestie, so this page is straight out of User Contributed Perl Documentation, section 3pm, and its whole title vibe is Test2:...Preload(3pm). Let's get into it. π
β¨ NAME β¨
Test2::Harness::Runner::Preload β the DSL for building complex stage-based preload tools. it's giving infrastructure but make it cute. π¦
πΈ DESCRIPTION πΈ
So Test2::Harness can preload libraries for a perf boost, right? but this module is like, "bestie, we can go further." it hands you the tools to build a whole more complex preload. and not just one β you can build multiple preload stages, and each stage gets its own process, and tests can run from whichever specific stage they want. which means: multiple different preload states, all ready to run tests from. iconic. π
β SYNOPSIS β
π USING YOUR PRELOAD
The -P or --preload options work for your custom preload modules exactly like they do for regular modules. Yath knows the difference and acts accordingly. no cap.
yath test -PMy::Preload
π¦ WRITING YOUR PRELOAD
package My::Preload;
use strict;
use warnings;
# This imports several useful tools, and puts the necessary meta-data in
# your package to identify it as a special preload.
use Test2::Harness::Runner::Preload;
# You must specify at least one stage.
stage Moose => sub {
# Preload can be called multiple times, and can load multiple modules
# per call. Order is preserved.
preload 'Moose', 'Moose::Role';
preload 'Scalar::Util', 'List::Util';
# preload can also be given a sub if you have some custom code to run
# at a specific point in the load order
preload sub {
# Do something before loading Try::Tiny
...
};
preload 'Try::Tiny';
# Tell the runner to watch this file for changes, if it does change run
# the sub instead of the usual reload process. This lets you reload
# configs and other non-perl files, or allows you to use a custom
# reload sub for perl files.
watch 'path/to/file' => sub { ... };
# You can also use watch inside preload subs:
preload sub {
watch 'path/to/file' => sub { ... };
};
# In app code you can add watches dynamically when applicable:
preload sub {
... # inside app code
if ($INC{'Test2/Harness/Runner/DepTracer.pm'}) {
if (my $active = Test2::Harness::Runner::DepTracer->ACTIVE) {
$active->add_callback('path/to/file' => sub { ... });
}
}
...
};
# Eager means tests from nested stages can be run in this stage as
# well, this is useful if the nested stage takes a long time to load as
# it allows yath to start running tests sooner instead of waiting for
# the stage to finish loading. Once the nested stage is loaded tests
# intended for it will start running from it instead.
eager();
# default means this stage is the one to use if the test does not
# specify a stage.
default();
# These are hooks that let you run arbitrary code at specific points in
# the process. pre_fork happens just before forking to run a test.
# post_fork happens just after forking for a test. pre_launch happens
# as late as possible before the test starts executing (post fork,
# after $0 and other special state are reset).
pre_fork sub { ... };
post_fork sub { ... };
pre_launch sub { ... };
# Stages can be nested, nested ones build off the previous stage, but
# are in a forked process to avoid contaminating the parent.
stage Types => sub {
preload 'MooseX::Types';
};
};
# Alternative stage that loads Moo instead of Moose
stage Moo => sub {
preload 'Moo';
...
};
π HARNESS DIRECTIVES IN PRELOADS
okay so if you're using a staged preload and the --reload option, you can drop 'CHURN' directives into your files so only the sections you're actually working on get reloaded. this is lowkey a lifesaver when a file can't be fully reloaded, or when fully reloading it is expensive. wrap your subroutines in the churn directives and yath will reload only those subroutines. obsessed.
sub do_not_reload_this { ... {
# HARNESS-CHURN-START
sub reload_this_one {
...
}
sub reload_this_one_too {
...
}
# HARNESS-CHURN-STOP
sub this_is_not_reloaded { ... }
You can put as many churn sections as you want in as many preloaded modules as you want. fr fr. If a change gets detected, only the churn sections get reloaded. and how do the churn sections get reloaded? yath takes the source between the start and stop markers and runs it in an eval like this:
eval <<EOT
package MODULE_FROM_FILENAME;
use strict;
use warnings;
no warnings 'redefine';
#line $line_number $file
$YOUR_CODE
;1;
EOT
In most cases that's enough to swap the old sub out for the new one. If the automatically determined package isn't correct, you can add a package FOO; statement inside the markers. If the strict/warnings settings aren't to your specifications, you can add overrides inside the markers. literally any valid perl code can go inside the markers. β¨
CAVEATS: be aware they do not have their original scope, and that can lead to problems if you're not paying attention. π Variables outside your markers are not accessible, and lexical variables you put inside your markers will be "new" on each reload β which can cause confusion if you have lexicals used by multiple subs where some are inside churn blocks and others aren't, so bestie, best not to do that. Package variables work a bit better, but any assignment lines get re-run. Soour $FOO;is fine (it does not change the value if it is set) butour $FOO = ...will reset the var on each reload. π
π EXPORTS π
$meta = TEST2_HARNESS_PRELOAD()$meta = $class->TEST2_HARNESS_PRELOAD()
This export provides the meta object, which is an instance of this class. The presence of this method is literally how Test2::Harness tells the difference between a regular module and a special preload library. iykyk. π₯
stage NAME => sub { ... }
This creates a new stage with the given NAME, then runs the coderef with the new stage set as the active one β the one that all the other functions here will operate on. Once the coderef returns, the active stage gets cleared. π
You can nest stages by calling this function again inside the codeblock.
NOTE: stage names ARE case sensitive. This can be confusing when you consider that most harness directives are all-caps. In the following case, the stage requested by the test and the stage defined in the library are NOT the same. π
In a test file:
# HARNESS-STAGE-FOO
In a preload library:
stage foo { ... }
Harness directives are all-caps, however the user data portion need not be, so this is fine:
# HARNESS-STAGE-foo
However, it is very easy to make the mistake of thinking it's case insensitive, and it's also easy to assume the 'foo' part of the harness directive must be all caps. In many cases it's smart to make your stage names all-caps. π
preload $module_namepreload @module_namespreload sub { ... }
This MUST be called inside a stage() builder coderef.
This adds modules to the list of libraries to preload. Order is preserved. You can also add coderefs to execute arbitrary code between module loads.
The coderef is called with no arguments, and its return is ignored. π
eager()
This MUST be called inside a stage() builder coderef.
This marks the active stage as being eager. An eager stage will start running tests for nested stages if it finds itself with no tests of its own to run before the nested stage can finish loading. The idea here is to avoid unused test slots when possible, which allows tests to complete sooner. slay. β‘
default()
This MUST be called inside a stage() builder coderef.
This MUST be called only once across ALL stages in a given library.
If multiple preload libraries are loaded then the first default set (based on load order) will be the default, others will not be honored. sorry bestie, first come first served. π
$stage_name = file_stage($test_file)
This is optional. If defined, this callback gets a chance to look at every file that's going to be run and assign them a stage. It may return undef or an empty list if it doesn't have a stage to assign. π¦
If multiple preload libraries define file_stage callbacks they'll be called in order, and the first one to return a stage name wins.
If no file_stage callbacks provide a stage for a file, then any harness directives declaring a stage will be honored. If no stage is ever assigned, then the test will be run in the default stage.
pre_fork sub { ... }
This MUST be called inside a stage() builder coderef.
Add a callback to be run just before the preload-stage process forks to run the test. Note that any state changes here can affect future tests to be run. β οΈ
post_fork sub { ... }
This MUST be called inside a stage() builder coderef.
Add a callback to be run just after the preload-stage process forks to run the test. This is run as early as possible, so things like $0 may not be set properly yet.
pre_launch sub { ... }
This MUST be called inside a stage() builder coderef.
Add a callback to be run just before control of the test process is turned over to the test file itself. This is run as late as possible, so things like $0 should be set properly by then. π
π§ META-OBJECT π§
This class is also the meta-object used to construct a preload library. The methods are left undocumented because it's an implementation detail and you are not intended to directly use this object. hands off, bestie. π
π SOURCE π
The source code repository for Test2-Harness can be found at http://github.com/Test-More/Test2-Harness/.
π MAINTAINERS π
Chad Granum <exodist@cpan.org>
πΈ AUTHORS πΈ
Chad Granum <exodist@cpan.org>
π COPYRIGHT π
Copyright 2020 Chad Granum <exodist7@gmail.com>.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
See http://dev.perl.org/licenses/
and that's the whole page, bestie!! π
β¨ this was documented under perl v5.40.1, dated 2026-05-10, for the Test2:...Preload(3pm) page in the User Contributed Perl Documentation. mwah, ily, go build some stages π«Άπ
π¦ where this page comes from
- ubuntu stonking: libtest2-harness-perl 1.000172-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms