NAME
Assert::Conditional - conditionally-compiled code assertions
SYNOPSIS
# use them all unconditionally
use Assert::Conditional qw(:all -if 1);
# Use them based on some external conditional available
# at compile time.
use Assert::Conditional qw(:all)
=> -if => ( $ENV{DEBUG} && ! $ENV{NDEBUG} );
# Use them based on some external conditional available
# at compile time.
use Assert::Conditional qw(:all)
=> -unless => $ENV{RUNTIME} eq "production";
# Method that should be called in list context with two array refs
# as arguments, and which should have both a "cross_product" and
# a "cross_tees" method available to it.
sub some_method {
assert_list_context();
assert_object_method();
assert_argc(3);
my($self, $left, $right) = @_;
assert_arrayref($left);
assert_arrayref($right);
assert_can($self, "cross_product", "cross_tees");
...
assert_happy_code { $i > $j };
...
}
DESCRIPTION
C programmers have always had assert.h to conditionally compile assertions into their programs, but options available for Perl programmers are not so convenient.
Several assertion modules related to assertions exist on CPAN, but none works quite like this one does, probably due to differing design goals. There was nothing that allowed you to say what C programmers could say:
assert(colors > 10)
And then have the "colors > 10" bit included in the failure message if it didn't work, thanks to the C preprocessor. See "assert_happy_code" for a way to do that very same thing.
Runtime Control of Assertions
No matter what assertions you conditionally use, there may be times when you have a running piece of software that you want to change the assertion behavior of without changing the source code.
For that, the ASSERT_CONDITIONAL
environment variable is used to override the current defaults.
- never
-
Assertions are never imported, and even if you somehow manage to import them, they will never never make a peep nor raise an exception.
- always
-
Assertions are always imported, and even if you somehow manage to avoid importing them, they will still raise an exception on error. This is the default.
- carp
-
Assertions are always imported but they do not raise an exception if they fail; instead they all carp at you. This is true even if you somehow manage to call an assertion you haven't imported.
Note that if combined, you can get both effects:
ASSERT_CONDITIONAL="carp,always"
- handlers
-
Only usable in conjunction with another of the previous three, as in
ASSERT_CONDITIONAL="always,handlers"
Unless this option is specified,
$SIG{__WARN__}
and$SIG{__DIE__}
handlers will be suppressed if the assertion fails while the ensuing aconfess
orcarp
is needed.
These may be combined for stacked effects, but "never" cancels all of them. For example:
ASSERT_CONDITIONAL="carp,always"
ASSERT_CONDITIONAL="carp,handlers"
ASSERT_CONDITIONAL="carp,always,handlers"
Inventory of Assertions
Here in alphabetical order is the list of all assertions with their prototypes. Following this is a list of assertions grouped by category, and finally a description of what each one does.
assert_ainta ( $@ ) ;
assert_alnum ( $ ) ;
assert_alphabetic ( $ ) ;
assert_anyref ( $ ) ;
assert_argc ( ;$ ) ;
assert_argc_max ( $ ) ;
assert_argc_min ( $ ) ;
assert_argc_minmax ( $$ ) ;
assert_array_length ( \@ ;$) ;
assert_array_length_max ( \@ $ ) ;
assert_array_length_min ( \@ $ ) ;
assert_array_length_minmax ( \@ $$) ;
assert_array_nonempty ( \@ ) ;
assert_arrayref ( $ ) ;
assert_arrayref_nonempty ( $ ) ;
assert_ascii ( $ ) ;
assert_ascii_ident ( $ ) ;
assert_astral ( $ ) ;
assert_blank ( $ ) ;
assert_bmp ( $ ) ;
assert_box_number ( $ ) ;
assert_bytes ( $ ) ;
assert_can ( $@ ) ;
assert_cant ( $@ ) ;
assert_class_ainta ( $@ ) ;
assert_class_can ( $@ ) ;
assert_class_cant ( $@ ) ;
assert_class_isa ( $@ ) ;
assert_class_method ( ) ;
assert_coderef ( $ ) ;
assert_defined ( $ ) ;
assert_defined_value ( $ ) ;
assert_defined_variable ( \$ ) ;
assert_digits ( $ ) ;
assert_directory ( $ ) ;
assert_does ( $@ ) ;
assert_doesnt ( $@ ) ;
assert_dumped_core ( ;$ ) ;
assert_empty ( $ ) ;
assert_eq ( $$ ) ;
assert_eq_letters ( $$ ) ;
assert_even_number ( $ ) ;
assert_exited ( ;$ ) ;
assert_false ( $ ) ;
assert_fractional ( $ ) ;
assert_full_perl_ident ( $ ) ;
assert_globref ( $ ) ;
assert_happy_code ( & ) ;
assert_happy_exit ( ;$ ) ;
assert_hash_keys ( \% @ ) ;
assert_hash_keys_allowed ( \% @ ) ;
assert_hash_keys_allowed_and_required ( \% $ $ ) ;
assert_hash_keys_required ( \% @ ) ;
assert_hash_keys_required_and_allowed ( \% $ $ ) ;
assert_hash_nonempty ( \% ) ;
assert_hashref ( $ ) ;
assert_hashref_keys ( $@ ) ;
assert_hashref_keys_allowed ( $@ ) ;
assert_hashref_keys_allowed_and_required ( $$$ ) ;
assert_hashref_keys_required ( $@ ) ;
assert_hashref_keys_required_and_allowed ( $$$ ) ;
assert_hashref_nonempty ( $ ) ;
assert_hex_number ( $ ) ;
assert_in_list ( $@ ) ;
assert_in_numeric_range ( $$$ ) ;
assert_integer ( $ ) ;
assert_ioref ( $ ) ;
assert_is ( $$ ) ;
assert_isa ( $@ ) ;
assert_isnt ( $$ ) ;
assert_keys ( \[%$] @ ) ;
assert_known_package ( $ ) ;
assert_latin1 ( $ ) ;
assert_latinish ( $ ) ;
assert_legal_exit_status ( ;$ ) ;
assert_like ( $$ ) ;
assert_list_context ( ) ;
assert_list_nonempty ( @ ) ;
assert_locked ( \[%$] @ ) ;
assert_lowercased ( $ ) ;
assert_max_keys ( \[%$] @ ) ;
assert_method ( ) ;
assert_min_keys ( \[%$] @ ) ;
assert_minmax_keys ( \[%$] \[@$] \[@$] ) ;
assert_multi_line ( $ ) ;
assert_natural_number ( $ ) ;
assert_negative ( $ ) ;
assert_negative_integer ( $ ) ;
assert_nfc ( $ ) ;
assert_nfd ( $ ) ;
assert_nfkc ( $ ) ;
assert_nfkd ( $ ) ;
assert_no_coredump ( ;$ ) ;
assert_nonalphabetic ( $ ) ;
assert_nonascii ( $ ) ;
assert_nonastral ( $ ) ;
assert_nonblank ( $ ) ;
assert_nonbytes ( $ ) ;
assert_nonempty ( $ ) ;
assert_nonlist_context ( ) ;
assert_nonnegative ( $ ) ;
assert_nonnegative_integer ( $ ) ;
assert_nonnumeric ( $ ) ;
assert_nonobject ( $ ) ;
assert_nonpositive ( $ ) ;
assert_nonpositive_integer ( $ ) ;
assert_nonref ( $ ) ;
assert_nonvoid_context ( ) ;
assert_nonzero ( $ ) ;
assert_not_in_list ( $@ ) ;
assert_numeric ( $ ) ;
assert_object ( $ ) ;
assert_object_ainta ( $@ ) ;
assert_object_boolifies ( $ ) ;
assert_object_can ( $@ ) ;
assert_object_cant ( $@ ) ;
assert_object_isa ( $@ ) ;
assert_object_method ( ) ;
assert_object_nummifies ( $ ) ;
assert_object_overloads ( $@ ) ;
assert_object_stringifies ( $ ) ;
assert_odd_number ( $ ) ;
assert_open_handle ( $ ) ;
assert_positive ( $ ) ;
assert_positive_integer ( $ ) ;
assert_private_method ( ) ;
assert_protected_method ( ) ;
assert_public_method ( ) ;
assert_qualified_ident ( $ ) ;
assert_refref ( $ ) ;
assert_reftype ( $$ ) ;
assert_regex ( $ ) ;
assert_regular_file ( $ ) ;
assert_sad_exit ( ;$ ) ;
assert_scalar_context ( ) ;
assert_scalarref ( $ ) ;
assert_signalled ( ;$ ) ;
assert_signed_number ( $ ) ;
assert_simple_perl_ident ( $ ) ;
assert_single_line ( $ ) ;
assert_single_paragraph ( $ ) ;
assert_text_file ( $ ) ;
assert_tied ( \[$@*] ) ;
assert_tied_array ( \@ ) ;
assert_tied_arrayref ( $ ) ;
assert_tied_glob ( \* ) ;
assert_tied_globref ( $ ) ;
assert_tied_hash ( \% ) ;
assert_tied_hashref ( $ ) ;
assert_tied_referent ( $ ) ;
assert_tied_scalar ( \$ ) ;
assert_tied_scalarref ( $ ) ;
assert_true ( $ ) ;
assert_unblessed_ref ( $ ) ;
assert_undefined ( $ ) ;
assert_unhappy_code ( & ) ;
assert_unicode_ident ( $ ) ;
assert_unlike ( $$ ) ;
assert_unlocked ( \[%$] @ ) ;
assert_unsignalled ( ;$ ) ;
assert_untied ( \[$@%*] ) ;
assert_untied_array ( \@ ) ;
assert_untied_arrayref ( $ ) ;
assert_untied_glob ( \* ) ;
assert_untied_globref ( $ ) ;
assert_untied_hash ( \% ) ;
assert_untied_hashref ( $ ) ;
assert_untied_referent ( $ ) ;
assert_untied_scalar ( \$ ) ;
assert_untied_scalarref ( $ ) ;
assert_uppercased ( $ ) ;
assert_void_context ( ) ;
assert_whole_number ( $ ) ;
assert_wide_characters ( $ ) ;
assert_zero ( $ ) ;
All assertions have function prototypes; this helps you use them correctly, and in some cases casts the argument into scalar context, adds backslashes to pass things by reference, so you don't have to.
Export Tags
You may import all assertions or just some of them. When importing only some of them, you may wish to use an export tag to import a set of related assertions. Here is what each tag imports:
:all
-
"assert_ainta", "assert_alnum", "assert_alphabetic", "assert_anyref", "assert_argc", "assert_argc_max", "assert_argc_min", "assert_argc_minmax", "assert_array_length", "assert_array_length_max", "assert_array_length_min", "assert_array_length_minmax", "assert_array_nonempty", "assert_arrayref", "assert_arrayref_nonempty", "assert_ascii", "assert_ascii_ident", "assert_astral", "assert_blank", "assert_bmp", "assert_box_number", "assert_bytes", "assert_can", "assert_cant", "assert_class_ainta", "assert_class_can", "assert_class_cant", "assert_class_isa", "assert_class_method", "assert_coderef", "assert_defined", "assert_defined_value", "assert_defined_variable", "assert_digits", "assert_directory", "assert_does", "assert_doesnt", "assert_dumped_core", "assert_empty", "assert_eq", "assert_eq_letters", "assert_even_number", "assert_exited", "assert_false", "assert_fractional", "assert_full_perl_ident", "assert_globref", "assert_happy_code", "assert_happy_exit", "assert_hash_keys", "assert_hash_keys_allowed", "assert_hash_keys_allowed_and_required", "assert_hash_keys_required", "assert_hash_keys_required_and_allowed", "assert_hash_nonempty", "assert_hashref", "assert_hashref_keys", "assert_hashref_keys_allowed", "assert_hashref_keys_allowed_and_required", "assert_hashref_keys_required", "assert_hashref_keys_required_and_allowed", "assert_hashref_nonempty", "assert_hex_number", "assert_in_list", "assert_in_numeric_range", "assert_integer", "assert_ioref", "assert_is", "assert_isa", "assert_isnt", "assert_keys", "assert_known_package", "assert_latin1", "assert_latinish", "assert_legal_exit_status", "assert_like", "assert_list_context", "assert_list_nonempty", "assert_locked", "assert_lowercased", "assert_max_keys", "assert_method", "assert_min_keys", "assert_minmax_keys", "assert_multi_line", "assert_natural_number", "assert_negative", "assert_negative_integer", "assert_nfc", "assert_nfd", "assert_nfkc", "assert_nfkd", "assert_no_coredump", "assert_nonalphabetic", "assert_nonascii", "assert_nonastral", "assert_nonblank", "assert_nonbytes", "assert_nonempty", "assert_nonlist_context", "assert_nonnegative", "assert_nonnegative_integer", "assert_nonnumeric", "assert_nonobject", "assert_nonpositive", "assert_nonpositive_integer", "assert_nonref", "assert_nonvoid_context", "assert_nonzero", "assert_not_in_list", "assert_numeric", "assert_object", "assert_object_ainta", "assert_object_boolifies", "assert_object_can", "assert_object_cant", "assert_object_isa", "assert_object_method", "assert_object_nummifies", "assert_object_overloads", "assert_object_stringifies", "assert_odd_number", "assert_open_handle", "assert_positive", "assert_positive_integer", "assert_private_method", "assert_protected_method", "assert_public_method", "assert_qualified_ident", "assert_refref", "assert_reftype", "assert_regex", "assert_regular_file", "assert_sad_exit", "assert_scalar_context", "assert_scalarref", "assert_signalled", "assert_signed_number", "assert_simple_perl_ident", "assert_single_line", "assert_single_paragraph", "assert_text_file", "assert_tied", "assert_tied_array", "assert_tied_arrayref", "assert_tied_glob", "assert_tied_globref", "assert_tied_hash", "assert_tied_hashref", "assert_tied_referent", "assert_tied_scalar", "assert_tied_scalarref", "assert_true", "assert_unblessed_ref", "assert_undefined", "assert_unhappy_code", "assert_unicode_ident", "assert_unlike", "assert_unlocked", "assert_unsignalled", "assert_untied", "assert_untied_array", "assert_untied_arrayref", "assert_untied_glob", "assert_untied_globref", "assert_untied_hash", "assert_untied_hashref", "assert_untied_referent", "assert_untied_scalar", "assert_untied_scalarref", "assert_uppercased", "assert_void_context", "assert_whole_number", "assert_wide_characters", and "assert_zero".
:argc
-
"assert_argc", "assert_argc_max", "assert_argc_min", and "assert_argc_minmax".
:array
-
"assert_array_length", "assert_array_length_max", "assert_array_length_min", "assert_array_length_minmax", "assert_array_nonempty", "assert_arrayref", "assert_arrayref_nonempty", "assert_list_nonempty", "assert_tied_array", "assert_tied_arrayref", "assert_untied_array", and "assert_untied_arrayref".
:boolean
-
"assert_false", "assert_happy_code", "assert_true", and "assert_unhappy_code".
:case
:code
-
"assert_coderef", "assert_happy_code", and "assert_unhappy_code".
:context
-
"assert_list_context", "assert_nonlist_context", "assert_nonvoid_context", "assert_scalar_context", and "assert_void_context".
:file
-
"assert_directory", "assert_open_handle", "assert_regular_file", and "assert_text_file".
:glob
-
"assert_globref", "assert_tied_glob", "assert_tied_globref", "assert_untied_glob", and "assert_untied_globref".
:hash
-
"assert_hash_keys", "assert_hash_keys_allowed", "assert_hash_keys_allowed_and_required", "assert_hash_keys_required", "assert_hash_keys_required_and_allowed", "assert_hash_nonempty", "assert_hashref", "assert_hashref_keys", "assert_hashref_keys_allowed", "assert_hashref_keys_allowed_and_required", "assert_hashref_keys_required", "assert_hashref_keys_required_and_allowed", "assert_hashref_nonempty", "assert_keys", "assert_locked", "assert_max_keys", "assert_min_keys", "assert_minmax_keys", "assert_tied_hash", "assert_tied_hashref", "assert_unlocked", "assert_untied_hash", and "assert_untied_hashref".
:ident
-
"assert_ascii_ident", "assert_full_perl_ident", "assert_known_package", "assert_qualified_ident", and "assert_simple_perl_ident".
:io
:list
-
"assert_in_list", "assert_list_nonempty", and "assert_not_in_list".
:number
-
"assert_box_number", "assert_digits", "assert_even_number", "assert_fractional", "assert_hex_number", "assert_in_numeric_range", "assert_integer", "assert_natural_number", "assert_negative", "assert_negative_integer", "assert_nonnegative", "assert_nonnegative_integer", "assert_nonnumeric", "assert_nonpositive", "assert_nonpositive_integer", "assert_nonzero", "assert_numeric", "assert_odd_number", "assert_positive", "assert_positive_integer", "assert_signed_number", "assert_whole_number", and "assert_zero".
:object
-
"assert_ainta", "assert_can", "assert_cant", "assert_class_ainta", "assert_class_can", "assert_class_cant", "assert_class_isa", "assert_class_method", "assert_does", "assert_doesnt", "assert_isa", "assert_known_package", "assert_method", "assert_nonobject", "assert_object", "assert_object_ainta", "assert_object_boolifies", "assert_object_can", "assert_object_cant", "assert_object_isa", "assert_object_method", "assert_object_nummifies", "assert_object_overloads", "assert_object_stringifies", "assert_private_method", "assert_protected_method", "assert_public_method", "assert_reftype", and "assert_unblessed_ref".
:overload
-
"assert_object_boolifies", "assert_object_nummifies", "assert_object_overloads", and "assert_object_stringifies".
:process
-
"assert_dumped_core", "assert_exited", "assert_happy_exit", "assert_legal_exit_status", "assert_no_coredump", "assert_sad_exit", "assert_signalled", and "assert_unsignalled".
:ref
-
"assert_anyref", "assert_arrayref", "assert_coderef", "assert_globref", "assert_hashref", "assert_ioref", "assert_nonref", "assert_refref", "assert_reftype", "assert_scalarref", "assert_tied_arrayref", "assert_tied_globref", "assert_tied_hashref", "assert_tied_referent", "assert_tied_scalarref", "assert_unblessed_ref", "assert_untied_arrayref", "assert_untied_globref", "assert_untied_hashref", "assert_untied_referent", and "assert_untied_scalarref".
:regex
-
"assert_alnum", "assert_alphabetic", "assert_ascii", "assert_ascii_ident", "assert_blank", "assert_digits", "assert_full_perl_ident", "assert_hex_number", "assert_like", "assert_lowercased", "assert_multi_line", "assert_nonalphabetic", "assert_nonascii", "assert_nonblank", "assert_qualified_ident", "assert_regex", "assert_simple_perl_ident", "assert_single_line", "assert_single_paragraph", "assert_unicode_ident", "assert_unlike", and "assert_uppercased".
:scalar
-
"assert_defined", "assert_defined_value", "assert_defined_variable", "assert_false", "assert_scalarref", "assert_tied_scalar", "assert_tied_scalarref", "assert_true", "assert_undefined", "assert_untied_scalar", and "assert_untied_scalarref".
:string
-
"assert_alphabetic", "assert_ascii", "assert_blank", "assert_bytes", "assert_empty", "assert_eq", "assert_eq_letters", "assert_is", "assert_isnt", "assert_latin1", "assert_multi_line", "assert_nonalphabetic", "assert_nonascii", "assert_nonblank", "assert_nonbytes", "assert_nonempty", "assert_single_line", "assert_single_paragraph", and "assert_wide_characters".
:tie
-
"assert_tied", "assert_tied_array", "assert_tied_arrayref", "assert_tied_glob", "assert_tied_globref", "assert_tied_hash", "assert_tied_hashref", "assert_tied_referent", "assert_tied_scalar", "assert_tied_scalarref", "assert_untied", "assert_untied_array", "assert_untied_arrayref", "assert_untied_glob", "assert_untied_globref", "assert_untied_hash", "assert_untied_hashref", "assert_untied_referent", "assert_untied_scalar", and "assert_untied_scalarref".
:unicode
-
"assert_astral", "assert_bmp", "assert_eq", "assert_eq_letters", "assert_latin1", "assert_latinish", "assert_nfc", "assert_nfd", "assert_nfkc", "assert_nfkd", and "assert_nonastral".
Assertions about Calling Context
These assertions inspect their immediate caller’s wantarray
.
- assert_list_context()
-
Current function was called in list context.
- assert_nonlist_context()
-
Current function was not called in list context.
- assert_scalar_context()
-
Current function was called in scalar context.
- assert_void_context()
-
Current function was called in void context.
- assert_nonvoid_context()
-
Current function was not called in void context.
Assertions about Scalars
These assertions don't pay any special attention to objects, so the normal effects of evaluating an object where a regular scalar is expected apply.
- assert_true(EXPR)
-
The scalar expression EXPR is true according to Perl's sense of Boolean logic, the sort of thing you would put in an
if (...)
condition to have its block run.If this assertion fails, it will not report the original expression. You should therefore strongly consider using "assert_happy_code" instead for more descriptive error messages because "assert_happy_code" will show the literal expression that was expected to be true but which unexpectedly evaluated to false.
- assert_false(EXPR)
-
The scalar expression EXPR is true according to Perl's sense of Boolean logic, the sort of thing you would put in an
unless
) condition to have its block run.If this assertion fails, it will not report the original expression. You should therefore strongly consider using "assert_unhappy_code" instead for more descriptive error messages, because "assert_unhappy_code" will display the literal expression that was expected to be false but which unexpectedly evaluated to true.
False values in Perl are the undefined value, both kinds of empty string (
q()
and!1
), the string of length one whose only character is an ASCIIDIGIT ZERO
, and those numbers which evaluate to zero. Strings that evaluate to numeric zero other than the previously stated exemption are not false, such as the notorious value"0 but true"
sometimes returned by theioctl
,fcntl
, andsyscall
system calls. - assert_defined(EXPR)
-
The scalar EXPR argument is defined. Consider using one of either "assert_defined_variable" or "assert_defined_value" to better document your intention.
- assert_undefined(EXPR)
-
The scalar EXPR argument is not defined.
- assert_defined_variable(SCALAR)
-
The scalar variable argument SCALAR is defined. This is safer to call than "assert_defined_value" because it requires an actual scalar variable with a leading dollar sign, so generates a compiler error if you try to pass it other sigils.
- assert_defined_value(EXPR)
-
The scalar EXPR is defined.
- assert_is(THIS, THAT)
-
The two defined non-ref arguments test true for "string equality", codepoint by codepoint, using the built-in
eq
operator.When called on objects with operator overloads, their
eq
overload or if necessary their stringification overloads will thereofre be honored but this test is not otherwise in any fashion recursive or object-aware.This is not the same as equivalent Unicode strings. For that, use "assert_eq" to compare normalized Unicode strings, and use "assert_eq_letters" to compare only their letters but disregard the rest.
- assert_isnt(THIS, THAT)
-
The two defined non-ref arguments test false for string equality with the
ne
operator. The expected overloads are therefore honored, but this test is not otherwise in any fashion recursive or object-aware.
Assertions about Numbers
Most of the assertions in this section treat their arguments as numbers. When called on objects with operator overloads, their evaluation will therefore trigger a 0+
nummification overload in preference to a ""
stringification overload if the former exists. Otherwise normal fallback rules apply as documented in the overload pragma.
- assert_numeric(EXPR)
-
The defined non-ref argument looks like a number suitable for implicit conversion according to the builtin "looks_like_number" in Scalar::Util predicate.
- assert_nonnumeric(EXPR)
-
The defined non-ref argument does not look like a number suitable for implicit conversion, again per "looks_like_number" in Scalar::Util.
- assert_positive(EXPR)
-
The defined non-ref argument is numerically greater than zero.
- assert_nonpositive(EXPR)
-
The defined non-ref argument is numerically less than or equal to zero.
- assert_negative(EXPR)
-
The defined non-ref argument is numerically less than zero.
- assert_nonnegative(EXPR)
-
The defined non-ref argument is numerically greater than or equal to numeric zero.
- assert_zero(EXPR)
-
The defined non-ref argument is numerically equal to numeric zero.
- assert_nonzero(EXPR)
-
The defined non-ref argument is not numerically equal to numeric zero.
- assert_integer(EXPR)
-
The defined non-ref numeric argument has no fractional part.
- assert_fractional(EXPR)
-
The defined non-ref numeric argument has a fractional part.
- assert_signed_number(EXPR)
-
The defined non-ref numeric argument has a leading sign, ASCII
-
or+
. A UnicodeMINUS SIGN
does not currently count because Perl will not respect it for implicit string-to-number conversions. - assert_natural_number(EXPR)
-
One of the counting numbers: 1, 2, 3, . . .
- assert_whole_number(EXPR)
-
A natural number or zero.
- assert_positive_integer(EXPR)
-
An integer greater than zero.
- assert_nonpositive_integer(EXPR)
-
An integer not greater than zero.
- assert_negative_integer(EXPR)
-
An integer less than zero.
- assert_nonnegative_integer(EXPR)
-
An integer that's zero or below.
- assert_hex_number(EXPR)
-
Beyond an optional leading
0x
, the argument contains only ASCII hex digits, making it suitable for feeding to thehex
function. - assert_box_number(EXPR)
-
The argument treated as a string is suitable for feeding to Perl's
oct
function, so a non-negative integer with an optional leading0b
for binary,0o
or0
for octal, or0x
for hex.Mnemonic: "box numbers" are binary, octal, or hex numbers.
- assert_even_number(EXPR)
-
The defined non-ref integer expression must be an even multiple of two.
- assert_odd_number(EXPR)
-
The defined non-ref integer expression must not be an even multiple of two.
- assert_in_numeric_range(NUMBER, LOW, HIGH)
-
The scalar NUMBER argument falls between the numeric range specified in the next two scalar arguments; that is, it must be at least as great as the LOW end of the range but no higher than the HIGH end of the range.
It's like writing either of these:
assert_happy_code { $number >= $low && $number <= $high }; assert_true($number >= $low && $number <= $high);
Assertions about Strings
- assert_empty(EXPR)
-
The defined non-ref argument is of zero length.
- assert_nonempty(EXPR)
-
The defined non-ref argument is not of zero length.
- assert_blank(EXPR)
-
The defined non-ref argument has at most only whitespace characters in it. It may be length zero.
- assert_nonblank(EXPR)
-
The defined non-ref argument has at least one non-whitespace character in it.
- assert_single_line(EXPR)
-
The defined non-empty string argument has at most one optional linebreak grapheme (
\R
, so a CRLF or vertical whitespace line newline, carriage return, and form feed) at the very end. It is disqualified if it has a linebreak anywhere shy of the end, or more than one of them at the end. - assert_multi_line(EXPR)
-
Non-empty string argument has at most one optional linebreak grapheme (
\R
, so a CRLF or vertical whitespace line newline, carriage return, and form feed) at the very end. It is disqualified if it has a linebreak anywhere shy of the end, or more than one of them at the end. - assert_single_paragraph(EXPR)
-
Non-empty string argument has at any number of linebreak graphemes at the very end only. It is disqualified if it has linebreaks anywhere shy of the end, but does not care how many are there.
- assert_bytes(EXPR)
-
Argument contains only code points between 0x00 and 0xFF. Such data is suitable for writing out as binary bytes.
- assert_nonbytes(EXPR)
-
Argument contains code points greater than 0xFF. Such data must first be encoded when written.
- assert_wide_characters(EXPR)
-
The same thing as saying that it contains non-bytes.
Assertions about Regexes
- assert_nonascii(EXPR)
-
Argument contains at least one code point larger that 127.
- assert_ascii(EXPR)
-
Argument contains only code points less than 128.
- assert_alphabetic(EXPR)
-
Argument contains only alphabetic code points, but not necessarily ASCII ones.
- assert_nonalphabetic(EXPR)
-
Argument contains only non-alphabetic code points, but not necessarily ASCII ones.
- assert_alnum(EXPR)
-
Argument contains only alphabetic or numeric code points, but not necessarily ASCII ones.
- assert_digits(EXPR)
-
Argument contains only ASCII digits.
- assert_uppercased(EXPR)
-
Argument will not change if uppercased.
- assert_lowercased(EXPR)
-
Argument will not change if lowercased.
- assert_unicode_ident(EXPR)
-
Argument is a legal Unicode identifier, so one beginning with an (X)ID Start code point and having any number of (X)ID Continue code points following. Note that Perl identifiers are somewhat different from this.
- assert_simple_perl_ident(EXPR)
-
Like a Unicode identifier but which may also start with connector punctuation like underscores. No package separators are allowed, however. Sigils do not count.
Also, special variables like
$.
or${^PREMATCH}
will not work either, since passing this function strings like.
and{
and^
are all beyond the pale. - assert_full_perl_ident(EXPR)
-
Like a simple Perl identifier but which also allows for optional package separators, either
::
or'
. - assert_qualified_ident(EXPR)
-
Like a full Perl identifier but with mandatory package separators, either
::
or'
. - assert_ascii_ident(EXPR)
-
What most people think of as an identifier, one with only ASCII letter, digits, and underscores, and which cannot begin with a digit.
- assert_regex(ARG)
-
The argument must be a compile Regexp object.
- assert_like(STRING, REGEX)
-
The string, which must be a defined non-reference, matches the pattern, which must be a compiled Regexp object produces by the
qr
operator. - assert_unlike(STRING, REGEX)
-
The string, which must be a defined non-reference, cannot match the pattern, which must be a compiled Regexp object produces by the
qr
operator.
Assertions about Unicode
- assert_latin1(ARG)
-
The argument contains only code points from U+0000 through U+00FF.
- assert_latinish(ARG)
-
The argument contains only characters from the Latin, Common, or Inherited scripts.
- assert_astral(ARG)
-
The argument contains at least one code point larger than U+FFFF, so those above Plane 0.
- assert_nonastral(ARG)
-
Argument contains only code points from U+0000 through U+FFFF.
- assert_bmp(ARG)
-
An alias for "assert_nonastral".
The argument contains only code points in the Basic Multilingual Plain; that is, in Plane 0.
- assert_nfc(ARG)
-
The argument is in Unicode Normalization Form C, formed by canonical decomposition followed by canonical composition.
- assert_nfkc(ARG)
-
The argument is in Unicode Normalization Form KC, formed by compatible decomposition followed by compatible composition.
- assert_nfd(ARG)
-
The argument is in Unicode Normalization Form D, formed by canonical decomposition.
- assert_nfkd(ARG)
-
The argument is in Unicode Normalization Form KD, formed by compatible decomposition.
- assert_eq(THIS, THAT)
-
The two strings have the same NFC forms using the
eq
operator. This means that default ignorable code points will throw of the equality check.This is not the same as "assert_is". You may well want the next assertion instead.
- assert_eq_letters(THIS, THAT)
-
The two strings test equal when considered only at the primary strength (letters only) using the Unicode Collation Algorithm. That means that case (whether upper-, lower-, or titecase), non-letters, and combining marks are ignored, as are other default ignorable code points.
Assertions about Lists
- assert_in_list(STRING, LIST)
-
The first argument must occur in the list following it.
- assert_not_in_list(STRING, LIST)
-
The first argument must not occur in the list following it.
- assert_list_nonempty(LIST)
-
The list must have at least one element, although that element does not have to nonblank or even defined.
Assertions about Arrays
- assert_array_nonempty( ARRAY )
-
The array must at least one element.
- assert_arrayref_nonempty( ARRAYREF )
-
The array reference must refer to an existing array with at least one element.
- assert_array_length(ARRAY, [ LENGTH ])
-
The array must have the number of elements specified in the optional second argument. If the second argument is omitted, any non-zero length will do.
- assert_array_length_min(ARRAY, MIN_ELEMENTS)
-
The array must have at least as many elements as specified by the number in the second argument.
- assert_array_length_max(ARRAY, MAX_ELEMENTS)
-
The array must have no more elements than the number specified in the second argument.
- assert_array_length_minmax(ARRAY, MIN_ELEMENTS, MAX_ELEMENTS)
-
The array must have at least as many elements as the number given in the second element, but no more than the one in the third.
Assertions about Argument Counts
WARNING: These assertions are incompatible with Test::Exception because they inspect their caller
's args via @DB::args
, and that module wipes those out from visibility.
- assert_argc()
- assert_argc(COUNT)
-
assert_argc(3); # must be exactly 3 args assert_argc( ); # must be at least 1 arg
The function must have been passed the number of arguments specified in the optional COUNT argument. When called without a COUNT argument, any non-zero number of arguments will do.
Does not work under Test::Exception.
- assert_argc_min(COUNT)
-
The function must have been passed at least as many arguments as specified in the COUNT argument.
Does not work under Test::Exception.
- assert_argc_max(COUNT)
-
The function must have been passed at most as arguments as specified in the COUNT argument.
Does not work under Test::Exception.
Does not work under Test::Exception.
- assert_argc_minmax(MIN, MAX)
-
The function must have been passed at least as many arguments as specified by the MIN, but no more than specified in the MAX.
Does not work under Test::Exception.
Assertions about Hashes
- assert_hash_nonempty(HASH)
-
The hash must have at least one key.
- assert_hashref_nonempty(HASHREF)
-
The hashref's referent must have at least one key.
- assert_keys(HASH | HASHREF, KEY_LIST)
-
my @exact_keys = qw[larry moe curly]; assert_keys(%some_hash, @exact_keys);
The HASH must have all keys in the non-empty KEY_LIST but no others.
This is especially useful when you've got a hash that you're treating as a "fixed record" data-type, as though it were a C
struct
: all fields are guaranteed to be present and nothing else.This assertion also accepts a HASHREF argument instead, but it still must be an actual variable.
That is, if instead of a HASH variable is passed as the first argument, a scalar variable holding a hashref is passed, then the hash referenced is subject to this constraint. In other words, you get a single level of auto-dereference to get to the hash, but the price of that is that this must be an lvalue not an rvalue: it must be an actual variable. For example:
my @exact_keys = qw[larry moe curly]; assert_keys($some_hashref, @exact_keys); assert_keys($hash_of_hashes{SOME_FIELD}, @exact_keys); assert_keys($array_of_hashes[42], @exact_keys);
Perl enforces this at compile-time by making you use either a
%
or$
sigil on the first argument to this assertion.For many uses of exact hashes like this, you would be well advised to lock the hash keys once you've validated them.
use Hash::Util qw(lock_keys); my @exact_keys = qw[larry moe curly]; assert_keys(%some_hash, @exact_keys); lock_keys(%some_hash);
or
use Hash::Util qw(lock_ref_keys); my @exact_keys = qw[larry moe curly]; assert_keys($some_hashref, @exact_keys); lock_ref_keys($some_hashref);
Now the keys are locked down to keep your honest, although the values can be still be changed. See Hash::Util.
- assert_min_keys(HASH | HASHREF, KEY_LIST)
-
assert_min_keys(%hash, qw[blue green red]); assert_min_keys($hashref, qw[blue green red]);
Asserts that the hash or hashref argument contains at least the keys mentioned in the non-empty key list.
- assert_max_keys(HASH | HASHREF, KEY_LIST)
-
assert_max_keys(%hash, qw[violet indigo blue cyan green yellow orange red]); assert_max_keys($hashref, qw[violet indigo blue cyan green yellow orange red]);
Asserts that the hash or hashref argument contains at most the keys mentioned in the non-empty key list. Consider locking your hash instead of just checking for unwanted keys. The locking will make sure that no other keys than these can be added to the hash:
lock_keys(%hash, qw[violet indigo blue cyan green yellow orange red]); lock_keys_ref($hashref, qw[violet indigo blue cyan green yellow orange red]);
Now you don't have to call "assert_max_keys" at all.
- assert_minmax_keys(HASH | HASHREF, MIN_ARRAY | MIN_ARRAYREF, MAX_ARRAY | MAX_ARRAYREF)
-
@minkeys = qw[red blue green]; @maxkeys = (@minkeys, qw[orange yellow cyan indigo]); assert_minmax_keys(%hash, @minkeys, @maxkeys); assert_minmax_keys($hashref, @minkeys, @maxkeys);
Asserts that the hash or hashref argument contains no other keys than the maximum allowed ones specified, and that all of those from the minimum required set exist. The arguments must be actual variables (lvalues), not merely anonymous values.
You can also pass the two pairs of minimum and maximum keys as scalar variables holding arrayrefs instead:
$minkeyref = \@minkeys; $maxkeyref = \@maxkeys; assert_minmax_keys(%hash, $minkeyref, $maxkeyref); assert_minmax_keys($hashref, $minkeyref, $maxkeyref); @minmax = ($minkeyref, $maxkeyref); assert_minmax_keys(%hash, $minmax[0], $minmax[1]); assert_minmax_keys($hashref, $minmax[0], $minmax[1]);
If you're careful to pass three refs of the right sorts in, you can actually use this if you circumvent prototype checking:
&assert_minmax_keys(\%hash, @minmax); &assert_minmax_keys( $hashref, @minmax);
- assert_locked(HASH | HASHREF)
-
WARNING: Only available under version 0.15 and greater of Hash::Util, first found in perl v5.17.
assert_locked(%hash); assert_locked($hashref); assert_locked($array_of_hashes[0]); assert_locked($arrayref_of_hashes->[0]); assert_locked($hash_of_hashes{FIELD}); assert_locked($hashref_of_hashes->{FIELD});
The argument, which must be either a hash variable or else a scalar variable holding a hashref, must have locked keys.
- assert_unlocked(HASH | HASHREF)
-
WARNING: Only available under version 0.15 and greater of Hash::Util, first found in perl v5.17.
assert_unlocked(%hash); assert_unlocked($hashref); assert_unlocked($array_of_hashes[0]); assert_unlocked($arrayref_of_hashes->[0]); assert_unlocked($hash_of_hashes{FIELD}); assert_unlocked($hashref_of_hashes->{FIELD});
The argument, which must be either a hash variable or else a scalar variable holding a hashref, must not have locked keys.
Legacy Assertions about Hashes
You should usually prefer "assert_keys", "assert_min_keys", "assert_max_keys", and "assert_minmax_keys" over the assertions in this section, since those have better names and aren't so finicky about their first argument. The following assertions are retained for backwards compatibility, but internally they all turn into one of those four.
The thing to remember with these is that "required" keys really means at least these keys, while "allowed" keys really means at most these keys. If you need those to be the same set, then just use "assert_keys" directly.
- assert_hash_keys(HASH, KEY_LIST)
-
WARNING: This does not mean what you think it means. Don't use it.
This function is misnamed; it is the deprecated, confusing, legacy version of "assert_min_keys". It really means "assert_hash_keys_required", which in turn means "has at most these keys". It does not mean has these exact keys and nothing else.
For that, you want "assert_keys".
- assert_hash_keys_required(HASH, KEY_LIST)
-
assert_hash_keys_required(%hash, qw[name rank serno]);
This is the legacy version of "assert_min_keys". Means "has at most these keys".
Each key specified in the key list must exist in the hash, but it's ok if there are other non-required keys.
If immediately after you validate the required keys from the KEY_LIST, you intend to validate the allowed keys using that same KEY_LIST because you're required to have all your allowed keys:
my @keys = qw[name rank serno]; assert_hash_keys_required(%hash, @keys); assert_hash_keys_allowed (%hash, @keys);
Then it would be faster to just call "assert_keys" in the first place.
my @keys = qw[name rank serno]; assert_keys(%hash, @keys);
However, if you plan to lock the hash when you're done validating it, then you can let the key-locker do the "allowed" step implicitly:
use Hash::Util qw(lock_keys); my @required = qw[name rank serno]; my @allowed = (@required, qw[spouse]); assert_hash_keys_required(%hash, @required); lock_keys(%hash, @allowed);
- assert_hash_keys_allowed(HASH, KEY_LIST)
-
This is the legacy version of "assert_max_keys". Means "has at least these keys".
Only keys in the non-empty KEY_LIST are allowed in the HASH, bit if some of those aren't there yet, that's ok.
For many applications of a hash, once you've validated that its keys are all allowed, you would be well-advised to lock its keys afterwards so that you know it can't ever get any stray keys added later that aren't in your KEY_LIST. For example:
use Hash::Util qw(lock_keys); my @possible_keys = qw[fee fie foe fum]; assert_hash_keys_allowed(%some_hash, @possible_keys); lock_keys(%some_hash, @possible_keys);
If you're going to do that, you should skip the assertion and let the core C code do all your checking for you, since it's much quicker that way.
use Hash::Util qw(lock_keys); my @possible_keys = qw[fee fie foe fum]; lock_keys(%some_hash, @possible_keys);
If the hash contains keys other than those listed, you'll still die at that point.
- assert_hash_keys_required_and_allowed(HASH, MIN_ARRAYREF, MAX_ARRAYREF)
-
This is the legacy version of "assert_minmax_keys", but it does allow you to pass the min and max arrayrefs as expressions rather than as named variables.
assert_hash_keys_required_and_allowed(%hash, [qw<fie fie foe>], [qw<fee foe foe fum]);
This lets you specify the minimal required keys and the maximum allowed keys in the same assertion. You must pass the required and allowed keys by arrayref so that they don't run together.
If you have them in arrays already, this is equivalent and is easier to understand:
@minkeys = qw(fee fie foe); @maxkeys = (@minkeys, "fum"); assert_minmax_keys(%hash, @minkeys, @maxkeys);
- assert_hash_keys_allowed_and_required(HASH, MAX_ARRAYREF, MIN_ARRAYREF)
-
assert_hash_keys_allowed_and_required(%hash, [qw<fee foe foe fum], [qw<fie fie foe>]);
This one flips the arguments, putting the maximum allowed keys before the minimum required keys. It does not required named variables as all three arguments the way "assert_minmax_keys" does.
- assert_hashref_keys(HASHREF, KEY_LIST)
-
WARNING: This does not mean what you think it means. Don't use it.
This function is misnamed; it is the deprecated, confusing, legacy version of "assert_min_keys". It really means "assert_hashref_keys_required", which in turn means "has at most these keys". It does not mean has these exact keys and nothing else.
For that, you want "assert_keys".
- assert_hashref_keys_required(HASHREF, KEY_LIST)
-
This is the legacy version of "assert_min_keys".
Means "has at least these keys".
Each key specified in the non-empty KEY_LIST must exist in the HASHREF's referent, but it's ok if there are other non-required keys.
See also the equivalent "assert_min_keys" which works on both hashes and hashrefs.
- assert_hashref_keys_allowed(HASHREF, KEY_LIST)
-
This is the legacy version of "assert_max_keys".
Means "has at most these keys".
Only keys in the non-empty KEY_LIST are allowed in the hash by HASHREF, but no checks are done to make sure that those in particular are there yet.
For many applications of a hashref, once you've validated that its keys are all allowed, you would be well-advised to lock its keys afterwards to that you know it can't get any strays added later that aren't in your KEY_LIST. For example:
use Hash::Util qw(lock_ref_keys); my @allowed_keys = qw[fee fie foe fum]; assert_hashref_keys_allowed($hashref, @allowed_keys); lock_ref_keys($hashref, @allowed_keys);
See also the equivalent "assert_max_keys" which works on both hashes and hashrefs.
- assert_hashref_keys_required_and_allowed(HASH, MIN_ARRAYREF, MAX_ARRAYREF)
-
assert_hashref_keys_required_and_allowed(%hash, [qw<fie fie foe>], [qw<fee foe foe fum]);
This is the reference version of "assert_hash_keys_required_and_allowed".
See also "assert_minmax_keys", which allowed both hashes and hashrefs as the first argument, but requires either arrays or scalar variables holding arrayrefs in the other two arguments.
- assert_hashref_keys_allowed_and_required(HASH, MAX_ARRAYREF, MIN_ARRAYREF)
-
assert_hash_keys_allowed_and_required(%hash, [qw<fee foe foe fum], [qw<fie fie foe>]);
This is the legacy version of "assert_minmax_keys", but it does allow you to pass the min and max arrayrefs as expressions rather than as named variables. The assert_minmax_keys assertion requires either array variables or scalar variables holding arrayrefs in the other two arguments.
This is the reference version of "assert_hash_keys_allowed_and_required".
Assertions about References
- assert_anyref(ARG)
-
Argument must be a reference.
- assert_nonref(ARG)
-
Argument must not be a reference.
- assert_reftype(TYPE, REF)
-
The basic type of the reference must match the one specified.
- assert_globref(ARG)
-
Argument must be a GLOB ref.
- assert_ioref(ARG)
-
Argument must be a IO ref. You probably don't want this; you probably want "assert_open_handle".
- assert_coderef(ARG)
-
Argument must be a CODE ref.
- assert_hashref(ARG)
-
Argument must be a HASH ref.
- assert_arrayref(ARG)
-
Argument must be an ARRAY ref.
- assert_scalarref(ARG)
-
Argument must be a SCALAR ref.
- assert_refref(ARG)
-
Argument must be a REF ref.
- assert_unblessed_ref(ARG)
-
Scalar argument must be a ref of any sort but not a blessed one.
Assertions about Objects
- assert_method()
-
Function must have at least one argument.
- assert_object_method()
-
First argument to function must be blessed.
- assert_class_method()
-
First argument to function must not be blessed.
- assert_public_method()
-
Just like "assert_method". In other words, it makes sure that there's an invocant, but beyond that does nothing other than add a bit of declarative syntax to help document your intent.
Does not work under Test::Exception.
- assert_private_method()
-
Must have been called by a sub compiled from the same file and package.
Now, you would think this would be a trivial check, and it should be, but the fluid-programming folks have decided they love to wrap and rewrap and unwrap and rerewrap functions so that their stacks are a lie. There are uncountably many ways to "wrap" subroutines in perl, all of which introduce extra frames that "shouldn't" be there and which cause this assertion to suddenly fail. As a sop to one of the more common ways, frames whose calling package is Class::MOP::Method::Wrapped are deliberately exempt from this check, and are skipped over.
Moose roles do not have access to private methods, only to protected ones. See next.
Does not work under Test::Exception.
- assert_protected_method()
-
The current sub must have been called by this package or from that of one its subclasses.
Or...
Or...
Or...
Or something about Moose roles, whatever those are. If you use them, then use this assertion at your own risk, but it seems to work.
Maybe.
The protection racket is a terrible business model. Strongly consider forbidding all access. A simpler life is a better life.
See also MooseX::Privacy.
Does not work under Test::Exception.
- assert_known_package(ARG)
-
The specified argument's package symbol table is not empty.
- assert_object(ARG)
-
Argument must be an object.
- assert_nonobject(ARG)
-
Argument must not be an object.
- assert_can(INVOCANT, METHOD_LIST)
-
The invocant, which can be a package name or an object but not an unblessed reference, can invoke all the methods listed.
- assert_cant(INVOCANT, METHOD_LIST)
-
The invocant, which can be a package name or an object but not an unblessed reference, cannot invoke any of the methods listed.
- assert_object_can(OBJECT, METHOD_LIST)
-
The object can invoke all of the methods listed.
- assert_object_cant(OBJECT, METHOD_LIST)
-
The object cannot invoke any of the methods listed.
- assert_class_can(CLASS, METHOD_LIST)
-
The known class can invoke all the methods listed.
- assert_class_cant(CLASS, METHOD_LIST)
-
The known class cannot invoke any of the methods listed.
- assert_isa(INVOCANT, CLASS_LIST)
-
The invocant, which can be a package name or an object but not an unblessed reference, must be a subclass of each class listed.
- assert_ainta(INVOCANT, CLASS_LIST)
-
The invocant cannot be a subclass of any class listed.
- assert_object_isa(OBJECT, CLASS_LIST)
-
The object must be a subclass of each class listed.
- assert_object_ainta
-
The object cannot be a subclass of any class listed.
- assert_class_isa(CLASS, CLASS_LIST)
-
The known class must be a subclass of each class listed.
- assert_class_ainta(CLASS, CLASS_LIST)
-
The known class cannot be a subclass of any class listed.
- assert_does(INVOCANT, CLASS_LIST)
-
The invocant must
->DOES
each class in the class list. - assert_doesnt(INVOCANT, CLASS_LIST)
-
The invocant must not
->DOES
any class in the class list. - assert_object_overloads(OBJECT [, OP_LIST ])
-
assert_object_overloads($some_object); assert_object_overloads($some_object, qw(+ += ++));
The OBJECT argument must have overloaded operators.
If any operators are given in the OP_LIST, then each of these must also have an overload method.
See overload.
- assert_object_stringifies(OBJECT)
-
The OBJECT argument must have an overloaded stringification operator.
- assert_object_nummifies(OBJECT)
-
The OBJECT argument must have an overloaded nummification operator.
(And yes, I meant to spell it this way: nummify rhymes with mummify and dummify, not with humify and fumify. We aren't talking about making an object numinous, which is something else entirely.)
- assert_object_boolifies(OBJECT)
-
The OBJECT argument must have an overloaded boolification operator.
- assert_tied(VARIABLE))
-
The VARIABLE argument must be a tied
$scalar
,@array
,%hash
, or*glob
. - assert_untied(VARIABLE)
-
The VARIABLE argument must not be a tied
$scalar
,@array
,%hash
, or*glob
. - assert_tied_referent(REF)
-
The REF argument must be a reference to a tied
$scalar
,@array
,%hash
, or*glob
.Consider that have this arrangement:
tie my %hash, "DB_File", "/some/path"; my $hashref = \%hash;
You could use
assert_tied(%hash);
or you could use
assert_tied_referent($hashref);
But you could not use
assert_tied($hashref);
Because that would ask whether
$hashref
itself has been tied, not whether the thing it's referring to has been. For that, you would useassert_tied_hashref($hashref);
- assert_untied_referent(REF)
-
The REF argument must not be a reference to a tied
$scalar
,@array
,%hash
, or*glob
. - assert_tied_scalar(SCALAR)
-
The SCALAR argument must be tied to a class.
- assert_untied_scalar(SCALAR)
-
The SCALAR argument must not be tied to a class.
- assert_tied_scalarref(SCALARREF)
-
The scalar referenced by SCALARREf must be tied to a class.
- assert_untied_scalarref(SCALARREF)
-
The scalar referenced by SCALARREf must not be tied to a class.
- assert_tied_array(ARRAY)
-
The ARRAY argument must be tied to a class.
- assert_untied_array(ARRAY)
-
The ARRAY argument must not be tied to a class.
- assert_tied_arrayref(ARRAYREF)
-
The array referenced by ARRAYREf must be tied to a class.
- assert_untied_arrayref(ARRAYREF)
-
The array referenced by ARRAYREf must not be tied to a class.
- assert_tied_hash(HASH)
-
The HASH argument must be tied to a class.
- assert_untied_hash(HASH)
-
The HASH argument must not be tied to a class.
- assert_tied_hashref(HASHREF)
-
The hash referenced by HASHREf must be tied to a class.
- assert_untied_hashref(HASHREF)
-
The hash referenced by HASHREf must not be tied to a class.
- assert_tied_glob(GLOB)
-
The GLOB argument must be tied to a class.
- assert_untied_glob(GLOB)
-
The GLOB argument must not be tied to a class.
- assert_tied_globref(GLOBREF)
-
The typeglob referenced by GLOBREf must be tied to a class.
- assert_untied_globref(GLOBREF)
-
The typeglob referenced by GLOBREf must not be tied to a class.
Assertions about Code
- assert_happy_code(CODE_BLOCK)
-
The supplied code block returns true.
This one and the next give nice error messages, but are not wholly removed from your program's parse tree at compile time is assertions are off: the argument is not called, but an empty function is.
For example, if you want to assert that you have more than 10 elements in your @colors array, you would write:
assert_happy_code { @colors > 10 };
If the return value of that code block is false, then you'll see something like this:
happy-test[96620]: botched assertion assert_happy_code: Happy test { @colors > 10 } is sadly false, bailing out at happy-test[96620] line 38.
When there is more than one statement, then the block is presented with newlines. For example:
assert_happy_code { if (@colors < 10) { @allowed > 5; } else { @required > 5; } };
would indicate its failure this way:
happy-test[96620]: botched assertion assert_happy_code: Happy test { if (@colors < 10) { @allowed > 5; } else { @required > 5; } } is sadly false, bailing out at happy-test line 38.
Notice how you can't tell which bit failed there, so it's best to use simple "boolean" expressions.
- assert_unhappy_code(CODE_BLOCK)
-
The supplied code block returns false. For example:
assert_unhappy_code { @colors < 100 };
would say something like this if the assert fails:
unhappy-test[96692]: botched assertion assert_unhappy_code: Unhappy assertion { @colors < 100 } is sadly true, bailing out at unhappy-test line 42.
Assertions about Files
- assert_open_handle(ARG)
-
The argument represents an open filehandle.
- assert_regular_file(ARG)
-
The argument is a regular file.
- assert_text_file(ARG)
-
The argument is a regular file and a text file.
- assert_directory(ARG)
-
The argument is a directory.
Assertions about Processes
All these assertions take an optional status argument as would be found in the $?
variable. If not status argument is passed, the $?
is used by default.
- assert_legal_exit_status( [ STATUS ])
-
The numeric value fits in 16 bits.
- assert_signalled( [ STATUS ])
-
The process was signalled.
- assert_unsignalled( [ STATUS ])
-
The process was not signalled.
- assert_dumped_core( [ STATUS ])
-
The process dumped core.
- assert_no_coredump( [ STATUS ])
-
The process did not dump core.
- assert_exited( [ STATUS ])
-
The process was not signalled, but rather exited either explicitly or implicitly.
- assert_happy_exit( [ STATUS ])
-
The process was not signalled and exited with an exit status of zero.
- assert_sad_exit( [ STATUS ])
-
The process was not signalled but exited with a non-zero exit status.
EXAMPLES
Suppose your team has decided that assertions should be governed by an environment variable called RUNTIME_MODE
. You want assertions enabled unless that variable is set to the string "production", or if there is an NDEBUG
variable set. And you want all the assertions except for those related to files or processes; that is, you don't want those two classes of assertions to be fatal in non-production, but the others you do.
You could call the module this way:
use Env qw(RUNTIME_MODE NDEBUG);
use Assert::Conditional ":all",
-unless => ($RUNTIME_MODE eq "production" || $DEBUG);
use Assert::Conditional qw(:file :process"), -if => 0;
On the other hand, you don't want everybody to have to remember to type that in exactly the same way in every module that uses it. So you want to create a simpler interface where the whole team just says
use MyAsserts;
and it does the rest. Here's one way to do that:
package MyAsserts;
use v5.10;
use strict;
use warnings;
use Env qw(RUNTIME_MODE NDEBUG);
use Assert::Conditional ":all",
-unless => ($RUNTIME_MODE eq "production" || $NDEBUG);
use Assert::Conditional qw(:file :process),
-if => 0;
our @ISA = 'Exporter';
our @EXPORT = @Assert::Conditional::EXPORT_OK;
our %EXPORT_TAGS = %Assert::Conditional::EXPORT_TAGS;
Notice the module you wrote is just a regular exporter, not a fancier conditional one. You've hidden the conditional part inside your module so that everyone using it will get the same rules.
Imagine a program that enables all assertions except those related to argument counts, and then runs through a bunch of them before hitting a failed assertion, at which point you get a stack dump about the failure:
$ perl -Ilib tests/test-assert
check function called with 1 2 3
test-assert[19009]: botched assertion assert_happy_code: Happy test { $i > $j } is sadly false, bailing out at tests/test-assert line 27.
Beginning stack dump in Assert::Conditional::Utils::botch at lib/Assert/Conditional/Utils.pm line 413, <DATA> line 1.
Assert::Conditional::Utils::botch('happy test $i > $j is sadly false') called at lib/Assert/Conditional.pm line 2558
Assert::Conditional::_run_code_test('CODE(0x7f965a0025a0)', 1) called at lib/Assert/Conditional.pm line 2579
Assert::Conditional::assert_happy_code('CODE(0x7f965a0025a0)') called at tests/test-assert line 27
Anything::But::Main::Just::To::See::If::It::Works::check(1, 2, 3) called at tests/test-assert line 15
Here is that tests/test-assert program:
#!/usr/bin/env perl
package Anything::But::Main::Just::To::See::If::It::Works;
use strict;
use warnings;
use Assert::Conditional qw(:all) => -if => 1;
use Assert::Conditional qw(:argc) => -if => 0;
my $data = <DATA>;
assert_bytes($data);
my ($i, $j) = (25, 624);
assert_numeric($_) for $i, $j;
my $a = check(1 .. 1+int(rand 3));
exit(0);
sub check {
assert_nonlist_context();
assert_argc();
assert_argc(37);
assert_argc_min(37);
my @args = @_;
print "check function called with @args\n";
assert_open_handle(*DATA);
assert_happy_code {$i < $j};
assert_happy_code {$i > $j};
assert_unhappy_code {$i < $j};
assert_unhappy_code {$i > $j};
check_args(4, 2);
assert_array_length(@_);
assert_array_length(@_, 11);
assert_argc_minmax(-54, 10);
assert_unhappy_code(sub {$i < $j});
assert_array_length_min(@_ => 20);
assert_class_method();
assert_void_context();
assert_list_context();
assert_nonlist_context();
assert_scalar_context();
assert_nonvoid_context();
assert_in_numeric_range($i, 10, 30);
assert_unhappy_code(\&check_args);
return undef;
}
sub check_args {
print "checking args for oddity\n";
assert_odd_number(int(rand(10)));
}
__DATA__
stuff
The reason the first failure is $i > $j
one is because the earlier assertions either passed ("assert_nonlist_context", "assert_open_handle") or were skipped because argc assertions were explicitly disabled.
However, if you instead ran the program this way, you would override that skipping of argc checked, and so it would blow up right away there:
$ ASSERT_CONDITIONAL=always perl -I lib tests/test-assert
test-assert[19107]: botched assertion assert_argc: Have 3 arguments but wanted 37, bailing out at tests/test-assert line 21.
Beginning stack dump in Assert::Conditional::Utils::botch at lib/Assert/Conditional/Utils.pm line 413, <DATA> line 1.
Assert::Conditional::Utils::botch('have 3 arguments but wanted 37') called at lib/Assert/Conditional/Utils.pm line 480
Assert::Conditional::Utils::botch_have_thing_wanted('HAVE', 3, 'THING', 'argument', 'WANTED', 37) called at lib/Assert/Conditional/Utils.pm line 455
Assert::Conditional::Utils::botch_argc(3, 37) called at lib/Assert/Conditional.pm line 2119
Assert::Conditional::assert_argc(37) called at tests/test-assert line 21
Anything::But::Main::Just::To::See::If::It::Works::check(1, 2, 3) called at tests/test-assert line 15
You can also disable all assertions completely, no matter the import was doing. Then they aren't ever called at all:
$ ASSERT_CONDITIONAL=never perl -I lib tests/test-assert
check function called with 1
checking args for oddity
Finally, you can run with assertions in carp mode. This runs them all, but they never raise an exception. Here's what an entire run would look like:
$ ASSERT_CONDITIONAL=carp perl -I lib tests/test-assert
test-assert[19129]: botched assertion assert_argc: Have 2 arguments but wanted 37 at tests/test-assert line 21.
test-assert[19129]: botched assertion assert_argc_min: Have 2 arguments but wanted 37 or more at tests/test-assert line 22.
check function called with 1 2
test-assert[19129]: botched assertion assert_happy_code: Happy test { $i > $j } is sadly false at tests/test-assert line 27.
test-assert[19129]: botched assertion assert_unhappy_code: Unhappy test { $i < $j } is sadly true at tests/test-assert line 28.
checking args for oddity
test-assert[19129]: botched assertion assert_odd_number: 4 should be odd at tests/test-assert line 49.
test-assert[19129]: botched assertion assert_array_length: Have 2 array elements but wanted 11 at tests/test-assert line 32.
test-assert[19129]: botched assertion assert_nonnegative: -54 should not be negative at tests/test-assert line 33.
test-assert[19129]: botched assertion assert_unhappy_code: Unhappy test { $i < $j } is sadly true at tests/test-assert line 34.
test-assert[19129]: botched assertion assert_array_length_min: Have 2 array elements but wanted 20 or more at tests/test-assert line 35.
test-assert[19129]: botched assertion assert_void_context: Wanted to be called in void context at tests/test-assert line 37.
test-assert[19129]: botched assertion assert_list_context: Wanted to be called in list context at tests/test-assert line 38.
checking args for oddity
test-assert[19129]: botched assertion assert_unhappy_code: Unhappy test { Anything::But::Main::Just::To::See::If::It::Works::check_args() } is sadly true at tests/test-assert line 43.
Notice how even though those assertions botch, they don't bail out of your program.
ENVIRONMENT
ASSERT_CONDITIONAL
The ASSERT_CONDITIONAL
variable controls the behavior of the underlying botch
function from Assert::Conditional::Utils, and also of the the conditional importing itself. If unset, assertions are on.
Its allowable values are:
- ASSERT_CONDITIONAL=never
-
Assertions are never imported, and even if you somehow manage to import them, they will never never make a peep nor raise an exception.
- ASSERT_CONDITIONAL=always
-
Assertions are always imported, and even if you somehow manage to avoid importing them, they will still raise an exception on error.
- ASSERT_CONDITIONAL=carp
-
Assertions are always imported but they do not raise an exception if they fail; instead they all carp at you. This is true even if you manage to call an assertion you haven't imported.
ASSERT_CONDITIONAL_ALLOW_HANDLERS
Normally, any user-registered pseudo-signal handlers in $SIG{__WARN__}
or $SIG{__DIE__}
are locally ignored when a failed assertion needs to generate a confess
(or under ASSERT_CONDITIONAL=carp
, a carp
).
Enabling this option from the environment leaves those handlers active instead, which for example means that if you have a $SIG{__WARN__}
handler that promotes a warning into a dying, even a carped assertion failure will kill you.
ASSERT_CONDITIONAL_BUILD_POD
This is used internally by the build tools to construct the pod for the exporter tag groups. See the etc/generate-exporter-pod script in the module source directory, which sets that variable and then runs this very module as an executable program instead of requiring it. Sneaky, I know.
ASSERT_CONDITIONAL_DEBUG
This adds some debugging used when for debugging the assertions themselves, and in their import/export handling; These are also triggered by $Exporter::Verbose
.
Currently this is used only in the attribute handlers that register exports during compile time.
BACKGROUND NOTES
Here are the design goals for Assert::Conditional
:
Make easy things easy: by making assertions so easy to write and so cheap to use, no one will have any reason not to use them.
Pass as few arguments as you can to each assertion, and don't require an easily forgotten
... if DEBUG()
to disable them.Create a rich set of assertions related to Perl code to check things such as calling context, argument numbers and times, and various other assumptions about the code or the data.
These not only provide sanity checks while running, they also help make the code more readable. If a boolean test were all that one ever needed, there would only ever be a
test_ok
function. Richer function names are better.Provide descriptive failure messages that help pinpoint the exact error, not just "assertion failed".
Make assertions that can be made to disappear from your program without any runtime cost if needed, yet which can also be re-enabled through a runtime mechanism without touching the code.
Provide a way for assertions to be run and checked, but which are not fatal to the program. (Raise no exception.)
Allow assertions to be enabled or disabled either en masse or piecemeal, picking and choosing from sets of related assertions to enable or disable. In other words, make them work a bit like lexical warnings where you can say give me all of this group, except for these ones.
Require no complicated framework setup to use.
Make it obvious what went wrong.
Keep the implementation of each assertion as short and simple as possible. This documentation is much longer than the code itself.
Use nothing but Standard Perl save at great need.
Compatible to Perl version 5.10 whenever possible. (This didn't pan out; it needs 5.12.)
The initial alpha release was considered completely experimental, but even so all these goals were met. The only module required that is not part of the standard Perl release is the underlying Exporter::ConditionalSubs which this module inherits its import method from. That module is where (most of) the magic happens to make assertions get compiled out of your program. You should look at that module for how the "conditional importing" works.
SEE ALSO
The Exporter::ConditionalSubs module which this module is based on.
The Assert::Conditional::Utils module provides some semi-standalone utility functions.
CAVEATS AND PROVISOS
This is a beta release.
BUGS AND LIMITATIONS
Under versions of Perl previous to v5.12.1, Attribute::Handlers blows up with an internal error about a symbol going missing.
HISTORY
0.001 6 June 2015 23:28 MDT
- Initial alpha release
0.002 J June 2015 22:35 MDT
- MONGOLIAN VOWEL SEPARATOR is no longer whitespace in Unicode, so removed from test.
0.003 Tue Jun 30 05:47:16 MDT 2015
- Added assert_hash_keys_required and assert_hash_keys_allowed.
- Fixed some tests.
- Added bug report about Attribute::Handlers bug prior to 5.12.
0.004 11 Feb 2018 11:18 MST
- Suppress overloading in botch messages for object-related assertions (but not others).
- Don't carp if we're throwing an exception and exceptions are trapped.
- Support more than one word in ASSERT_CONDITIONAL (eg: "carp,always").
- If ASSERT_CONDITIONAL contains "handlers", don't block @SIG{__{WARN,DIE}__}.
- Don't let assert_isa die prematurely on an unblessed ref.
0.005 Sun May 20 20:40:25 CDT 2018
- Initial beta release.
- Reworked the hash key checkers into a simpler set: assert_keys, assert_min_keys, assert_max_keys, assert_minmax_keys.
- Added invocant-specific assertions: assert_{object,class}_{isa,ainta,can,cant}.
- Added assertions for ties, overloads, and locked hashes.
- Made assert_private_method work despite Moose wrappers.
- Added assert_protected_method that works despite Moose wrappers and roles.
- Improved the looks of the uncompiled code for assert_happy_code.
- Fixed botch() to identify the most distant stack frame not the nearest for the name of the failed assertion.
- Improved the reporting of some assertion failures.
0.006 Mon May 21 07:45:43 CDT 2018
- Use hash_{,un}locked not hashref_{,un}locked to support pre-5.16 perls.
- Unhid assert_unblessed_ref swallowed up by stray pod.
0.007 Mon May 21 19:13:58 CDT 2018
- Add missing Hash::Util version requirement for old perls to get hashref_unlock imported.
0.008 Tue May 22 11:51:37 CDT 2018
- Rewrite hash_unlocked missing till 5.16 as !hash_locked
- Add omitted etc/generate-exporter-pod to MANIFEST
0.009 Tue Aug 21 06:29:56 MDT 2018
- Delay slow calls to uca_sort till you really need them, credit Larry Leszczynski.
0.010 Sun Jul 19 13:52:00 MDT 2020
- Fix coredump in perl 5.12 by replacing UNITCHECK in Assert::Conditional::Util with normal execution at botton.
- Make perls below 5.18 work again by setting Hash::Util prereq in Makefile.PL to 0 because it's in the core only, never cpan.
- Only provide assert_locked and assert_unlocked if core Hash::Util v0.15 is there (starting perl v5.17).
- Bump version req of parent class Exporter::ConditionalSubs to v1.11.1 so we don't break Devel::Cover.
- Normalize Export sub attribute tracing so either $Exporter::Verbose=1 or env ASSERT_CONDITIONAL_DEBUG=1 work for both Assert::Conditional{,::Utils}.
- Mentioned $Exporter::Verbose support.
AUTHOR
Tom Christiansen <tchrist53147@gmail.com>
Thanks to Larry Leszczynski at Grant Street Group for making this module possible. Without it, my programs would be much slower, since before I added his module to my old and pre-existing assertion system, the assertions alone were taking up far too much CPU time.
LICENCE AND COPYRIGHT
Copyright (c) 2015-2018, Tom Christiansen <tchrist@perl.com>
. All Rights Reserved.
This module is free software; you can redistribute it and/or