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.
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.
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.
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, or in electronic mail to the author.
AUTHOR
Thomas R. Wyant, III wyant at cpan dot org
COPYRIGHT AND LICENSE
Copyright (C) 2019-2020 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.