NAME
Test2::Tools::LoadModule - Test whether a module can be successfully loaded.
SYNOPSIS
use Test2::V0;
use Test2::Tools::LoadModule;
load_module_ok 'My::Module';
done_testing();
DESCRIPTION
This Test2::Tools module tests whether a module can be loaded, and optionally whether it has at least a given version, and exports specified symbols. It can also skip tests, or skip all tests, based on these criteria.
Test2::Manual::Testing::Migrating deals with migrating from Test::More to Test2::V0. It states that instead of require_ok()
you should simply use the require()
built-in, since a failure to load the required module or file will cause the test script to fail anyway. The same is said for use_ok()
.
In my perhaps-not-so-humble opinion this overlooks the fact that if you can not load the module you are testing, it may make sense to abort not just the individual test script but the entire test run. Put another way, the absence of an analogue to Test::More's require_ok()
means there is no analogue to
require_ok( 'My::Module' ) or BAIL_OUT();
This module restores that functionality.
Note that if you are using this module with testing tools that are not based on Test2::V0 you may have to tweak the load order of modules. I ran into this in the early phases of implementation, and fixed it for my own use by initializing the testing system as late as possible, but I can not promise that all such problems have been eliminated.
CAVEAT
Accurately testing whether a module can be loaded is more complicated than it might first appear. One known issue is that you can get a false pass if the module under test forgets to load a module it needs, but this module loads it for its own use.
Ideally this module would use nothing that Test2
does not, but that seems to require a fair amount of wheel-reinventing. What this module does try to do is to load the extra modules only if it really needs them. Specifically:
Getopt::Long is loaded only if arguments are passed to the use Test::Tools::LoadModule
statement.
File::Find and File::Spec are loaded only if all_modules_tried_ok() is called.
Because Carp and Exporter are used by Test2::API (at least as of version 1.302181
), this module makes no attempt to avoid their use.
SUBROUTINES
All subroutines documented below are exportable, either by name or using one of the following tags:
- :all exports all public exports;
- :default exports the default exports (i.e. :test2);
- :more exports require_ok() and use_ok();
- :test2 exports load_module_*(), and is the default.
load_module_ok
load_module_ok $module, $ver, $import, $name, @diag;
Prototype: (@)
.
This subroutine tests whether the specified module (not file) can be loaded. All arguments are optional. The arguments are:
- $module - the module name
-
This is the name of the module to be loaded. If unspecified or specified as
undef
, it defaults to the caller'sCLASS
if that exists; otherwise an exception is thrown. - $ver - the desired version number, or undef
-
If defined, the test fails if the installed module is not at least this version. An exception is thrown if the version number is invalid.
If
undef
, no version check is done. - $import - the import list as an array ref, or undef
-
This argument specifies the import list.
undef
means to import the default symbols,[]
means not to import anything, and a non-empty array reference means to import the specified symbols. - $name - the test name, or undef
-
If
undef
, the name defaults to the code used to load the module. Note that this code, and therefore the default name, may change without notice. - @diag - the desired diagnostics
-
Diagnostics are only issued on failure.
Argument validation failures are signalled by croak()
.
The module is loaded, and version checks and imports are done if specified. The test passes if all these succeed, and fails otherwise.
Note that any imports from the loaded module take place when this subroutine is called, which is normally at run time. Imported subroutines will be callable, provided you do not make use of prototypes or attributes.
If you want anything imported from the loaded module to be available for subsequent compilation (e.g. variables, subroutine prototypes) you will need to put the call to this subroutine in a BEGIN { }
block:
BEGIN { load_module_ok 'My::Module'; }
By default, $@
is appended to the diagnostics issued in the event of a load failure. If you want to omit this, or embed the value in your own text, see CONFIGURATION, below.
As a side effect, the names of all modules tried with this test are recorded, along with test results (pass/fail) for the use of all_modules_tried_ok().
load_module_or_skip
load_module_or_skip $module, $ver, $import, $name, $num;
Prototype: (@)
.
This subroutine performs the same loading actions as load_module_ok(), but no tests are performed. Instead, the specified number of tests is skipped if the load fails.
The arguments are the same as load_module_ok(), except that the fifth argument ($num
in the example) is the number of tests to skip, defaulting to 1
.
The $name
argument gives the skip message, and defaults to "Unable to ..."
where the ellipsis is the code used to load the module.
load_module_or_skip_all
load_module_or_skip_all $module, $ver, $import, $name;
Prototype: (@)
.
This subroutine performs the same loading actions as load_module_ok(), but no tests are performed. Instead, all tests are skipped if any part of the load fails.
The arguments are the same as load_module_ok(), except for the fact that diagnostics are not specified.
The $name
argument gives the skip message, and defaults to "Unable to ..."
where the ellipsis is the code used to load the module.
This subroutine can be called either at the top level or in a subtest, but either way it must be called before any actual tests in the file or subtest.
all_modules_tried_ok
all_modules_tried_ok
Added in version 0.002
.
Prototype: (@)
.
This test traverses any directories specified as arguments looking for Perl modules (defined as files whose names end in .pm). A failing test is generated for any such file not previously tested using load_module_ok().
If no directory is specified, the default is ( '/blib/lib', '/blib/arch' )
.
NOTE that no attempt is made to parse the file and determine its module name. The module is assumed from the part of the file path below the specified directory. So an explicit specification of lib/ will work (if that is where the modules are stored) but an explicit blib/ will not.
clear_modules_tried
clear_modules_tried
Added in version 0.002
.
Prototype: ()
.
This is not a test. It clears the record of modules tried by load_module_ok().
require_ok
require_ok $module;
Prototype: ($)
.
This subroutine is more or less the same as the Test::More subroutine of the same name. The argument is the name of the module to load.
use_ok
use_ok $module, @imports;
use_ok $module, $version, @imports;
Prototype: ($;@)
.
This subroutine is more or less the same as the Test::More subroutine of the same name. The arguments are the name of the module to load, and optional version (recognized by the equivalent of version::is_lax()
, and optional imports.
CONFIGURATION
The action of the load_module_*()
subroutines is configurable using POSIX-style options. If used as subroutine arguments they apply only to that subroutine call. If used as arguments to use()
, they apply to everything in the scope of the use()
, though this requires Perl 5.10 or above, and you must specify any desired imports.
These options are parsed by Getopt::Long (q.v.) in POSIX mode, so they must appear before non-option arguments. They are all documented double-dashed. A single leading dash is tolerated except in the form --option=argument
, where the double dash is required.
The following configuration options are available.
--require
If asserted, this possibly-badly-named Boolean option specifies that an undef
or unspecified import list imports nothing, while []
does the default import.
The default is -norequire
, which is the other way around. This is the way use()
works, which is what inspired the name of the option.
--req
This is just a shorter synonym for --require.
--load_error
--load_error 'Error: %s'
This option specifies the formatting of the load error for those subroutines that append it to the diagnostics. The value is interpreted as follows:
- A string containing
'%s'
-
or anything that looks like an
sprintf()
string substitution is interpreted verbatim as the sprintf format to use to format the error; - Any other true value (e.g.
1
) -
specifies the default,
'%s'
; - Any false value (e.g.
0
) -
specifies that
$@
should not be appended to the diagnostics at all.
For example, if you want your diagnostics to look like the Test::More require_ok()
diagnostics, you can do something like this (at least under Perl 5.10 or above):
{ # Begin scope
use Test2::Tools::LoadModule -load_error => 'Error: %s';
load_module_ok $my_module, undef, undef,
"require $my_module;", "Tried to require '$my_module'.";
...
}
# -load_error reverts to whatever it was before.
If you want your code to work under Perl 5.8, you can equivalently do
load_module_ok -load_error => 'Error: %s',
$my_module, undef, undef, "require $my_module;"
"Tried to require '$my_module'.";
Note that, while you can specify options on your initial load, if you do so you must specify your desired imports explicitly, as (e.g.)
use Test2::Tools::LoadModule
-load_error => 'Bummer! %s', ':default';
SEE ALSO
Test2::Manual::Testing::Migrating
SUPPORT
Support is by the author. Please file bug reports at https://rt.cpan.org/Public/Dist/Display.html?Name=Test2-Tools-LoadModule, https://github.com/trwyant/perl-Test2-Tools-LoadModule/issues, or in electronic mail to the author.
AUTHOR
Thomas R. Wyant, III wyant at cpan dot org
COPYRIGHT AND LICENSE
Copyright (C) 2019-2022 by Thomas R. Wyant, III
This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.
This program 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.