Precision Testing for Modern Perl

In a previous entry I discussed some of my favourite CPAN modules for testing Perl code.

I got to thinking... there are all these little frameworks on the CPAN like GID, and Modern::Perl, and Defaults::Modern, and Bubblegum which are basically little shims to load collections of "best practices" modules in a single line. For example:

   use Modern::Perl;

is basically a shortcut for:

   use IO::File qw();
   use IO::Handle qw();
   use strict;
   use warnings;
   use feature qw( :5.12 );
   use mro qw( c3 );

So why not do the same for test suites? Why not create a module that loads Test::More, and Test::Fatal, and Test::Warnings, and so on for me?

I know what you're thinking... Test::Most already exists. Test::Most is a good module, but it's been around a few years, and it shows. For example, it uses Test::Exception which is generally thought problematic compared to the newer Test::Fatal; similarly Test::Most uses Test::Warn where Test::Warnings might be a better choice. It's unlikely Ovid could ever change this situation without breaking a substantial number of the over 300 distributions that depend on Test::Most.

So I went and wrote Test::Modern which combines Test::More, Test::Fatal, Test::Warnings, and more. It automatically imports strict and warnings for you, and enables Test::Warnings' had_no_warnings feature so that any unexpected warnings will cause your tests to fail. It provides the ability to mark test scripts as being author, release, or extended tests, and skip them based on the presence or absence of environment variables (like Test::DescribeMe), or skip tests based on missing dependencies (like Test::Requires).

Because much modern Perl code is quite object-oriented, it provides an object_ok function combining Test::More's isa_ok and can_ok, a Test::Moose-inspired does_ok, a Test::API-powered class_api_ok, and a Test::CleanNamespaces-cribbed namespaces_clean.

Is it likely to be everything you need to test every project in one module? No. But of course using Test::Modern doesn't stop you from using other test modules too!

   use Test::Modern;
   use Test::URI;
   
   use MyApp::Person;
   
   object_ok(
      MyApp::Person->new_from_database(id => 42),
      isa   => [qw/ MyApp::Person Moose::Object /],
      does  => [qw/ MyApp::Role::Contact /],
      can   => [qw/ id name email website /],
      clean => 1,
      more  => sub {
         my $object = shift;
         is( $object->name, "Bob" );
         uri_scheme_ok( $object->website, 'http' );
      },
   );
   
   done_testing;

5 Comments

How will test::modern stay modern and not become aged like test::most? Perhaps a year import parameter like modern::perl to allow improvements/changes in future or something similar?

Hopefully Test::Postmodern will not be confused as a module for testing Moose, since Moose is postmodern.

Test::CleanNamespaces is back in active development and its underlying implementation is getting fixed up quite a lot, so it would probably be better to call into its version of clean_namespaces rather than copying its guts.

Leave a comment

About Toby Inkster

user-pic I'm tobyink on CPAN, IRC and PerlMonks.