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.
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)
which then gives me this handy output (line wrapped)
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.
Yes, this would cause the test script to fail on the first bad module and many people argue that this is a good thing. Worst case scenario (it's happened to me and it's a nightmare) is having use_ok fail but not kill the test suite. When that happens, you can have partially compiled code in memory and get strange errors in code that is bug free, segfaults, malicious green camels flying from your keyboard and so on.
If anything, I would recommend this technique to people who want it, not to everyone. I realize that while I may disagree with someone else's coding style, I don't want to tell them that they have no choice to but to adopt my coding style.