syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I'm not very strong on these Test::* modules. Here's the demo script (that should run on any machine that has Test::More and Test::Class installed):
package MyTest; use warnings; use base q{Test::Class}; use Test::More 'no_plan'; sub DEMO_1 : Tests { my $self = shift; $self->builder->skip('Wanting to skip the DEMO_1 tests'); my $results = { '1 / 2' => "0.5", '1 / 4' => 0.25, }; _verify($results); } sub DEMO_2 : Tests { my $results = { '1 / 8' => "0.125", '1 / 16' => 0.0625, }; _verify($results); } Test::Class->runtests; sub _verify { my $results = shift; for(keys(%$results)) { ok( eval($_) == $results->{$_}, "$_ == $results->{$_}"); } }
And here's the output I get on Win32, perl-5.10.0:
ok 1 # skip Wanting to skip the DEMO_1 tests ok 2 - 1 / 4 == 0.25 ok 3 - 1 / 2 == 0.5 ok 4 - 1 / 8 == 0.125 ok 5 - 1 / 16 == 0.0625 1..5
Now that's not quite what I intend. To begin with, the $self->builder->skip('Wanting to skip the DEMO_1 tests'); seems to be treated as a test (that passes) in itself. I'm not so concerned about that. What does concern me is that the 2 tests that I want to skip (namely, the 2 tests in sub DEMO_1) are still being run.

Is that a bug in Test::Builder ? ... perhaps as a result of the Test::Class environment ? ... or is it a Test::Class bug ? ... or is it just plain ol' incorrect usage on my part ?

Now, I've found a solution to the problem using the Test::More SKIP{} block. But is there a way I can get the sub DEMO_1 tests skipped by using that "$self->builder->skip()" approach ? Is there some other way of getting the desired result using Test::Builder::skip() ?

Cheers,
Rob

Replies are listed 'Best First'.
Re: Test::Builder::skip() not dwimming.
by massa (Hermit) on Sep 03, 2008 at 08:52 UTC
    AFAICT, it's just plain wrong usage on your part. Test::Builder::skip is just another test, like ok(...) etc.
    []s, HTH, Massa (κς,πμ,πλ)
      wrong usage on your part

      I've no reason to doubt you, but I'm still struggling to understand. The Test::Builder::skip documentation suggests to me that my usage is correct. It says that calling skip() "Skips the current test". By comparison, the skip_all() documentation says that skip_all() "Skips all the tests" - and that's exactly what happens when I replace:
      $self->builder->skip('Wanting to skip the DEMO_1 tests');
      with:
      $self->builder->skip_all('Wanting to skip all tests');
      With that change in place, things dwim perfectly. I find that all of the DEMO_1 and DEMO_2 tests are skipped - unless the DEMO_2 tests have been run first, in which case only the DEMO_1 tests get skipped.

      I also don't understand how one would apply a skip() test if it is "just another test, like ok(...)". massa, is there an example somewhere of how Test::Builder::skip() is meant to be put to a useful purpose ?

      Cheers,
      Rob
        The Test::Builder::skip documentation suggests to me that my usage is correct.

        No, it doesn't. skip() is documented under:

        Other Testing Methods These are methods which are used in the course of writing a test but are not themselves tests.

        It has nothing to do with control flow. It reports one test as skipped and then immediately returns. If you run a test afterward with an actual testing method, that's a new test.

        Of course, you should only use Test::Builder directly if you're writing a test module. Don't use it directly to run tests. Use Test::Class and Test::More.

Re: Test::Builder::skip() not dwimming.
by Anonymous Monk on Sep 03, 2008 at 10:50 UTC
      return 'Wanting to skip the DEMO_1 tests';

      Heh ... that's a nice solution to the problem ... and sort of obvious ... mumble, mumble :-)

      It doesn't really show me what one is supposed to do with Test::Builder::skip(), but I'm fast losing interest in that, anyway. Thanks, Anonymous Monk.

      Cheers,
      Rob
      Update: Thinking about this solution a little more, there's a couple of minor quibbles, iinm. Firstly, providing a return message is pointless, since one never gets to see it. Secondly, there's no acknowledgement of the fact that any tests have been skipped. (Still ... it's a rather clean solution.)
        Firstly, providing a return message is pointless, since one never gets to see it. Secondly, there's no acknowledgement of the fact that any tests have been skipped.

        Call diag() first, then return.