Test::Warnings - Test for warnings and the lack of them
Contents
Caveats
If you are using another module that sets its own warning handler (for example Devel::Confess or
diagnostics) your results may be mixed, as those handlers will interfere with this module's ability to
properly detect and capture warnings in their original form.
Contributors
• Graham Knop <haarg@haarg.org>
• Tina Müller <cpan2@tinita.de>
• A. Sinan Unur <nanis@cpan.org>
• Leon Timmermans <fawaka@gmail.com>
Copyright And Licence
This software is copyright (c) 2013 by Karen Etheridge.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5
programming language system itself.
perl v5.40.0 2025-02-06 Test::Warnings(3pm)
Description
If you've ever tried to use Test::NoWarnings to confirm there are no warnings generated by your tests,
combined with the convenience of "done_testing" to not have to declare a test count, you'll have
discovered that these two features do not play well together, as the test count will be calculated before
the warnings test is run, resulting in a TAP error. (See "examples/test_nowarnings.pl" in this
distribution for a demonstration.)
This module is intended to be used as a drop-in replacement for Test::NoWarnings: it also adds an extra
test, but runs this test before "done_testing" calculates the test count, rather than after. It does
this by hooking into "done_testing" as well as via an "END" block. You can declare a plan, or not, and
things will still Just Work.
It is actually equivalent to:
use Test::NoWarnings 1.04 ':early';
as warnings are still printed normally as they occur. You are safe, and enthusiastically encouraged, to
perform a global search-replace of the above with "use Test::Warnings;" whether or not your tests have a
plan.
It can also be used as a replacement for Test::Warn, if you wish to test the content of expected
warnings; read on to find out how.
Functions
The following functions are available for import (not included by default; you can also get all of them
by importing the tag ":all"):
allow_warnings([bool])-EXPERIMENTAL-MAYBEREMOVED
When passed a true value, or no value at all, subsequent warnings will not result in a test failure; when
passed a false value, subsequent warnings will result in a test failure. Initial value is "false".
When warnings are allowed, any warnings will instead be emitted via Test::Builder::note.
"allowing_warnings"-EXPERIMENTAL-MAYBEREMOVED
Returns whether we are currently allowing warnings (set by "allow_warnings" as described above).
"had_no_warnings(<optionaltestname>)"
Tests whether there have been any warnings so far, not preceded by an "allowing_warnings" call. It is
run automatically at the end of all tests, but can also be called manually at any time, as often as
desired.
"warnings({code})"
Given a code block, runs the block and returns a list of all the (not previously allowed via
"allow_warnings") warnings issued within. This lets you test for the presence of warnings that you not
only would allow, but must be issued. Testing functions are not provided; given the strings returned,
you can test these yourself using your favourite testing functions, such as Test::More::is or
Test::Deep::cmp_deeply.
You can use this construct as a replacement for Test::Warn::warnings_are:
is_deeply(
[ warnings { ... } ],
[
'warning message 1',
'warning message 2',
],
'got expected warnings',
);
or, to replace Test::Warn::warnings_like:
cmp_deeply(
[ warnings { ... } ],
bag( # ordering of messages doesn't matter
re(qr/warning message 1/),
re(qr/warning message 2/),
),
'got expected warnings (in any order)',
);
Warnings generated by this code block are NOT propagated further. However, since they are returned from
this function with their filename and line numbers intact, you can re-issue them yourself immediately
after calling warnings(...), if desired.
Note that "use Test::Warnings 'warnings'" will give you a "warnings" subroutine in your namespace (most
likely "main", if you're writing a test), so you (or things you load) can't subsequently do
"warnings->import" -- it will result in the error: "Not enough arguments for Test::Warnings::warnings at
..., near "warnings->import"". To work around this, either use the fully-qualified form
("Test::warnings") or make your calls to the "warnings" package first.
"warning({code})"
Same as "warnings( { code } )", except a scalar is always returned - the single warning produced, if
there was one, or an arrayref otherwise -- which can be more convenient to use than warnings() if you are
expecting exactly one warning.
However, you are advised to capture the result from warning() into a temp variable so you can dump its
value if it doesn't contain what you expect. e.g. with this test:
like(
warning { foo() },
qr/^this is a warning/,
'got a warning from foo()',
);
if you get two warnings (or none) back instead of one, you'll get an arrayref, which will result in an
unhelpful test failure message like:
# Failed test 'got a warning from foo()'
# at t/mytest.t line 10.
# 'ARRAY(0xdeadbeef)'
# doesn't match '(?^:^this is a warning)'
So instead, change your test to:
my $warning = warning { foo() };
like(
$warning,
qr/^this is a warning/,
'got a warning from foo()',
) or diag 'got warning(s): ', explain($warning);
allow_patterns
allow_patterns(qr/always allow this warning/);
{
my $temp = allow_patterns(qr/only allow in this scope/, qr/another temporary warning/);
... stuff ...
}
Given one or more regular expressions, in "qr/.../" form, add them to the allow-list (warnings will be
emitted with "note" rather than triggering the warning handler). If the return value is saved in a local
variable, the warning exemption will only be in effect for that local scope (the addition is reversed at
the end of the scope); otherwise, the effect is global.
disallow_patterns
Given one or more regular expressions, in "qr/.../" form, remove it from the allow-list. The pattern must
exactly match a pattern previously provided to "allow_patterns".
Import Options
":all"
Imports all functions listed above
":no_end_test"
Disables the addition of a "had_no_warnings" test via "END" or "done_testing"
":fail_on_warning"
When used, fail immediately when an unexempted warning is generated (as opposed to waiting until
"had_no_warnings" or "done_testing" is called).
I recommend you only turn this option on when debugging a test, to see where a surprise warning is coming
from, and rely on the end-of-tests check otherwise.
":report_warnings"
When used, had_no_warnings() will print all the unexempted warning content, in case it had been
suppressed earlier by other captures (such as "stderr_like" in Test::Output or "capture" in
Capture::Tiny).
Name
Test::Warnings - Test for warnings and the lack of them
Other Options
You can temporarily turn off the failure behaviour of this module, swapping it out for reporting (see
":report_warnings" above) with:
$ENV{PERL_TEST_WARNINGS_ONLY_REPORT_WARNINGS} = 1;
This can be useful for working around problematic modules that have warnings in newer Perl versions.
See Also
• Test::NoWarnings
• Test::FailWarnings
• blogs.perl.org: YANWT (Yet Another No-Warnings Tester)
<http://blogs.perl.org/users/ether/2013/03/yanwt-yet-another-no-warnings-tester.html>
• strictures - which makes all warnings fatal in tests, hence lessening the need for special warning
testing
• Test::Warn
• Test::Fatal
Support
Bugs may be submitted through the RT bug tracker <https://rt.cpan.org/Public/Dist/Display.html?Name=Test-
Warnings> (or bug-Test-Warnings@rt.cpan.org <mailto:bug-Test-Warnings@rt.cpan.org>).
There is also a mailing list available for users of this distribution, at
<http://lists.perl.org/list/perl-qa.html>.
There is also an irc channel available for users of this distribution, at "#perl" on "irc.perl.org"
<irc://irc.perl.org/#perl-qa>.
I am also usually active on irc, as 'ether' at "irc.perl.org" and "irc.libera.chat".
Synopsis
use Test::More;
use Test::Warnings;
pass('yay!');
done_testing;
emits TAP:
ok 1 - yay!
ok 2 - no (unexpected) warnings (via done_testing)
1..2
and:
use Test::More tests => 3;
use Test::Warnings 0.005 ':all';
pass('yay!');
like(warning { warn "oh noes!" }, qr/^oh noes/, 'we warned');
emits TAP:
ok 1 - yay!
ok 2 - we warned
ok 3 - no (unexpected) warnings (via END block)
1..3
To Do (Or: Possible Features Coming In Future Releases)
• allow_warnings(qr/.../) - allow some warnings and not others
• more sophisticated handling in subtests - if we save some state on the Test::Builder object itself,
we can allow warnings in a subtest and then the state will revert when the subtest ends, as well as
check for warnings at the end of every subtest via "done_testing".
• sugar for making failures TODO when testing outside an author environment
Version
version 0.038
