5

I want to add a test to my Perl distribution that requires a module Foo, but my distribution does not require Foo; only the test requires Foo. So I don't want to add the module to the dependencies, but instead I just want to skip the tests that require Foo if Foo is not available at build time.

What is the proper way to do this? Should I just wrap my Foo tests in an eval block along with use Foo;, so that the tests will not run if loading Foo fails? Or is there a more elegant way of doing it?

Ryan C. Thompson
  • 40,856
  • 28
  • 97
  • 159

4 Answers4

8

If all of the tests that require Some::Module are in a single file, it's easy to do:

use Test::More;

BEGIN {
    eval {
        require Some::Module;
        1;
    } or do {
        plan skip_all => "Some::Module is not available";
    };
}

(If you're using a test count like use Test::More tests => 42; then you need to also arrange to do plan tests => 42; if the require does succeed.)

If they're a smaller number of tests in a file that contains other stuff, then you could do something like:

our $HAVE_SOME_MODULE = 0;

BEGIN {
    eval {
        require Some::Module;
        $HAVE_SOME_MODULE = 1;
    };
}

# ... some other tests here

SKIP: {
    skip "Some::Module is not available", $num_skipped unless $HAVE_SOME_MODULE;
    # ... tests using Some::Module here
}
hobbs
  • 223,387
  • 19
  • 210
  • 288
6

Test::More has an option to skip if some condition is not satisfied, see below

SKIP: {
    eval { require Foo };

    skip "Foo not installed", 2 if $@;

    ## do something if Foo is installed
};
Pradeep
  • 3,093
  • 17
  • 21
2

From the documentation of Test::More:

SKIP: {
    eval { require HTML::Lint };
    skip "HTML::Lint not installed", 2 if $@;
    my $lint = new HTML::Lint;
    isa_ok( $lint, "HTML::Lint" );
    $lint->parse( $html );
    is( $lint->errors, 0, "No errors found in HTML" );
}
Matteo
  • 14,696
  • 9
  • 68
  • 106
2

Also, declare your test step requirement or recommendation (there's a difference) in the distro meta file. This will be picked up by a client performing the installation. At install time, the user can decide whether to install such a requirement permanently or discard it because it was only used for testing.

daxim
  • 39,270
  • 4
  • 65
  • 132
  • It seems like the `Test::More::skip` approach and your answer are complementary. The `skip` function allows me to skip tests that require a module that is unavailable, while your answer allows me to recommend that the client install the module without making it a hard dependency. If the client that is installing my dist decides not to install the optional testing dependency, will it then skip *all* the tests? Or will it somehow know which tests depend on that optional module and automatically skip only those? – Ryan C. Thompson Dec 13 '11 at 19:49
  • Or, to put it more simply, declaring an optional dependency is definitely something that I will do, but I don't see how it frees me from the obligation to handle the case where that optional module is not installed. – Ryan C. Thompson Dec 13 '11 at 19:56
  • Not quite, if it's a test requirement then it *will* be available. But I realise now that's not what the question is about, I misinterpreted what you meant with optional. You are right that the skip check is necessary in that case; I edited the answer to make it so. – daxim Dec 13 '11 at 20:03