Avoiding use_ok in t/00-load.t

There's a discussion on Perl-QA about whether the use of use_ok should be discouraged. I argue that it should be. It really doesn't gain us much, it's historically been buggy, and simply using the module is enough to cause a test failure if the module doesn't compile. So someone asked how to write this t/00-load.t if we didn't have use_ok:

#!perl -T
# -*- mode: cperl ; compile-command: "cd .. ; ./Build ; prove -vb t/00-*.t" -*-

use Test::More tests => 5;

BEGIN {
  use_ok( 'Test::Trap::Builder::TempFile' );
  use_ok( 'Test::Trap::Builder::SystemSafe' );
SKIP: {
    skip 'Lacking PerlIO', 1 unless eval "use PerlIO; 1";
    use_ok( 'Test::Trap::Builder::PerlIO' );
  }
  use_ok( 'Test::Trap::Builder' );
  use_ok( 'Test::Trap' ) or BAIL_OUT( "Nothing to test without the Test::Trap class" );    
}

diag( "Testing Test::Trap $Test::Trap::VERSION, Perl $], $^X" );

Here's a cleaner solution that relies on Perl's "use" builtin and the "if" pragma.

use Test::More tests => 1;

my $ok;
END { BAIL_OUT "Could not load all modules" unless $ok }
use Test::Trap::Builder::TempFile;                                                                                                            
use Test::Trap::Builder::SystemSafe;
use Test::Trap::Builder;
use Test::Trap;
use if eval "use PerlIO; 1", 'Test::Trap::Builder::PerlIO';
ok 1, 'All modules loaded successfully';
$ok = 1;

Yeah, I like that.

Naturally, it doesn't work if you're trying to dynamically discover the module names, but it could be made to work with that, too.

eval "use $module; 1"
  or BAIL_OUT $@ // "Zombie error";

Thanks to Ruud H.G. van Tol for correcting my eval.

3 Comments

I suggest putting in a diag that will show up at the top of the test run, too.

For instance, in ack I have this diag (line wrapped)

diag( "Testing App::Ack $App::Ack::VERSION,
File::Next $File::Next::VERSION, Perl $], $^X" );

which then gives me this handy output (line wrapped)

[10:08:57] t/00-load.t ............... 1/4
# Testing App::Ack 1.96, File::Next 1.06, Perl 5.012003, /opt/local/bin/perl

which covers the important things I want to know if someone comes to me with a test failure.

Wouldn't this method cause the test script to fail on the first bad module? Nothing frustrates me more than to have to go back and forth between my tests/compiler and my code because of stupid syntax mistakes. use_ok() lets me do a blanket run, test them all, find as many errors as possible, and then fix them all in one go. Some errors will hide other errors, but others won't.

So perhaps use_ok() can be considered a testing form of eval { use ...; 1 }.

That being said, it sounds like a style discussion. Neither opinion seems to have the power to completely overwhelm the other with logic. You say potato, I say potatoe.

About Ovid

user-pic Freelance Perl/Testing/Agile consultant and trainer. See http://www.allaroundtheworld.fr/ for our services. If you have a problem with Perl, we will solve it for you. And don't forget to buy my book! http://www.amazon.com/Beginning-Perl-Curtis-Poe/dp/1118013840/