NAME Moan - yet another "assert" module SYNOPSIS In "lib/MyApp/Database.pm": package MyApp::Database; use strict; use Moan; sub new { my ($class, $dbh) = @_; assert($dbh->isa('DBI::db'), 'Passed a database.'); assert($dbh->ping, 'Database is alive.'); bless [$dbh], $class; } sub dbh { $_[0][0]; } 1; In "bin/myapp.pl": #!/usr/bin/perl use MyApp::Database; use Moan; assert(defined $ENV{MYAPP_DB}, 'MYAPP_DB set'); my $db = MyApp::Database->new(DBI->connect($ENV{MYAPP_DB})); assert($db->isa('MyApp::Database'), 'Class OK'); # do something At the command-line: perl -Moan::more=MyApp::Database bin/myapp.pl DESCRIPTION Assertions are somewhere between inlined unit tests, checks against malicious input and executable comments. Assertions should be written to have no side-effects, and to always pass under normal circumstances. This is not the only Perl assertion module, and probably not the best, but it does what I need. This module requires Perl 5.10. Assertion Functions "assert($expression, $message, $tag)" Checks whether $expression evaluates to true. If not, the assertion fails (see "Assertion Consequences"). The second parameter $message is optional, and provides an error message to associate with the assertion. If omitted or undef, a default non-descriptive message is used. The third parameter $tag is a category for the assertion. This allows you to classify assertions and disable them by tag. If ommitted or undef, the default tag is the package name where the assertion occurred. The following two assertions are equivalent: package Foo::Bar; assert(1); package main; assert(1, undef, 'Foo::Bar'); Tags starting with a single colon are appended to the package name. So the following two assertions are equivalent: package Foo::Bar; assert(1, undef, ':quux'); package main; assert(1, undef, 'Foo::Bar:quux'); This means you have very little excuse for not namespacing your tags. For small packages, just leave the tag undefined and you'll get your assertion tagged with your package. For larger packages, use tags matching the expression "/^:(\w+)$/". Tags are in fact arbitrary strings, but you can save yourself headaches if you stick to the conventions above. "affirm {CODE_BLOCK} $message, $tag" Checks that the return value of the code is true. Good for more complex tests. (This is also more efficient than "assert" in cases where you've disabled assertion reporting, as "affirm" can avoid running the code block entirely. "diag $message, $tag" Strictly speaking, this does not actually make an assertion, but generates a diagnostic message (which is not usually shown). The "Assertion Consequences" section explains how to enable diagnostic messages on a per-tag basis. "no Moan" Disables moaning within a lexical block. Carp::Assert These functions are provided for rough compatibility with Carp::Assert. You should be able to more or less drop in "Moan" as a replacement: use Moan ':carpish'; "should($given, $expected, $message, $tag)" Equivalent to: assert($given ~~ $expected, $message, $tag); This is *slightly* different from "Carp::Assert::should" which uses "eq" instead of the smart match. "shouldnt($given, $expected, $message, $tag)" Equivalent to: assert(!($given ~~ $expected), $message, $tag); "DEBUG" Right now this just returns 1. Test::More These functions are provided for rough compatibility with Test::More. (Though note that "Moan" is not designed for writing module tests. It doesn't use TAP.) They are not exported by default. use Moan ':testmore'; "ok($expression, $message, $tag)" Largely the same as "assert", provided for people addicted to Test::More. "is($given, $expected, $message, $tag)" Equivalent to: ok($given eq $expected, $message, $tag); or ok($given == $expected, $message, $tag); ... depending on whether $expected looks like a number. "isnt($given, $expected, $message, $tag)" Equivalent to: ok($given ne $expected, $message, $tag); or ok($given != $expected, $message, $tag); ... depending on whether $expected looks like a number. "like($given, $expected, $message, $tag)" Equivalent to: ok($given =~ $expected, $message, $tag); "unlike($given, $expected, $message, $tag)" Equivalent to: ok($given !~ $expected, $message, $tag); "isa_ok($package_name, $class, $message, $tag)" "isa_ok($object, $class, $message, $tag)" Roughly equivalent to: ok($package_name->isa($class), $message, $tag); ok($object->isa($class), $message, $tag); ... but without failing horribly if $object is, say, an unblessed reference. "can_ok($package_name, $method, $message, $tag)" "can_ok($object, $method, $message, $tag)" Roughly equivalent to: ok($package_name->can($method), $message, $tag); ok($object->can($method), $message, $tag); ... but without failing horribly if $object is, say, an unblessed reference. Also Useful Here are some other functions that are occasionally useful. use Moan qw/:standard :testmore does_ok defined_ok blessed_ok/; "does_ok($package_name, $role, $message, $tag)" "does_ok($object, $role, $message, $tag)" Roughly equivalent to: ok($package_name->DOES($role), $message, $tag); ok($object->DOES($role), $message, $tag); ... but without failing horribly if $object is, say, an unblessed reference. "defined_ok($value, $message, $tag)" Pretty much identical to: ok(defined $value, $message, $tag); "blessed_ok($object, $message, $tag)" ok(Scalar::Util::blessed($object), $message, $tag); Export %EXPORT_TAGS = ( testmore => [qw/ok is isnt like unlike can_ok isa_ok/], carpish => [qw/assert affirm should shouldnt DEBUG/], standard => [qw/assert affirm diag/], ); @EXPORT = @{ $EXPORT_TAGS{standard} }; @EXPORT_OK = ( qw/blessed_ok defined_ok does_ok TRUE FALSE/, @{ $EXPORT_TAGS{standard} }, @{ $EXPORT_TAGS{testmore} }, @{ $EXPORT_TAGS{carpish} }, ); Yeah, you can export the constants TRUE and FALSE, just because they're so often handy to have. Assertion Consequences The normal consequence of an assertion is that a warning will be emitted, if the assertion does not hold (i.e. is false). Diagnostic messages ("diag") will not be printed. "Moan" can be kicked into a more verbose mode, where diagnostic messages are printed, and assertions that don't hold are accompanied by stacktracers. Just call "Moan->loudly" Moan->loudly(qw/MyApp::Database YourApp::Greaterface/); Each argument is a tag which you want to make "louder". The "/^:\w+$/" convention for tags that are local to your package will work, but to specify tags in other packages, you need to fully-qualify the names. For example, the tag ":connection" in package MyApp::Database could be made louder using: Moan->loudly('MyApp::Database:connection'); # sic Tags can be preceded with a minus to switch off the loudness feature. Regular expressions also work: Moan->loudly(qr/^MyApp::Database:(\w+)$/); There's currently no way to remove regular expressions from the list though, so use with caution. A special tag "ALL" makes all moaning louder. "-ALL" counteracts that. But what if you want to decrease "Moan"'s verbosity? As you might have guessed, "Moan->quietly" fulfils this role. It takes the same parameters as "Moan->loudly". If a tag has been quietened, then no warnings will be emitted for it whether the assertion holds or not. In fact, in many cases "Moan" can even avoid completely evaluating the assertion. Curiously, a tag can be made both loud and quiet, as the two features are quite separate. If a tag is both, then it will act quiet, except that warnings for diagnostic messages will be emitted. This should be considered an "at risk feature" (i.e. an arguable bug). There is also a "Moan->fatally" feature. This again takes the same parameters as "Moan->loudly". It makes failed assertions throw an exception (i.e. die). When "Moan" needs to throw an exception for an assertion, it checks to see if the tag is loud, and if not, appends all previous diagnostics to the exception. At some point, the exceptions thrown will probably be switched from strings to blessed objects in the next release. ("Moan::loudly", "Moan::quietly" and "Moan::fatally" also work.) The following functions are provided to check the behaviour of a tag: "Moan::is_loud($tag)" "Moan::is_quiet($tag)" "Moan::is_fatal($tag)" Command-Line Options "perl -Moan::quietly=tag1,tag2,tag3" - quietly "perl -Moan::loudly=tag1,tag2,tag3" - loudly "perl -d:oh=tag1,tag2,tag3" - loudly and fatally BUGS Please report any bugs to . SEE ALSO "Carp::Assert", "Test::More". AUTHOR Toby Inkster . COPYRIGHT AND LICENCE This software is copyright (c) 2011 by Toby Inkster. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. DISCLAIMER OF WARRANTIES THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.