Well, I ran into a snag.  I tried doing this:

{
    my($Skipped, $Skip_Reason);

    sub test_these (&;$) {
        my($code, $how_many) = @_;

        goto $code;

        # skip() will jump to here to bail out of the $code.
        CONSIDERED_HARMFUL: if( $Skipped ) {
            $how_many ||= 1;
            _skipped($Skip_Reason) for 1..$how_many;
        }

        # Reset our state.
        $Skipped = $Todo = 0;
        $Skip_Reason = $Todo_Reason = undef;
    }


    sub skip {
        $Skipped = 1;
        $Skip_Reason = shift;

        # Yes, an actual goto LABEL!  This is what lets skip() abort the
        # test_these block.
        goto CONSIDERED_HARMFUL;
    }


    sub todo {
        $Todo = 1;
        $Todo_Reason = shift;
    }
}


Problem is, the goto() inside skip() won't jump to the label inside
test_these().  The trouble is the goto $code, used to preserve the
caller's context (I want the test_these() block to act as much like a
normal block as possibe).  goto LABEL looks up the callstack for the
label, but the C<goto $code> hijacks the callstack, so it never sees
test_these() as part of it and thus can't see CONSIDERED_HARMFUL.

Two ways around this:

1) Don't worry about preserving caller() information in the
test_these() block.

This bothers me.  Ideally, a test function should interfere as little
as possible with the code.

2)  Try a real block.

I can make this work easily for skips:

        SKIP: {
            skip($why, $how_many) if $condition;

            ok( $some_test );
            ok( $some_other_test );
        }

using a little known hack that you can use C<last> from outside
(lexically outside) a block.

        sub skip {
            my($why, $how_many) = @_;
            $how_many ||= 1;

            _ok_skipped($why) for 1..$how_many;

            no warnings;
            last SKIP;
        }

that takes care of skip.  What about todo?  

        TODO: {
            todo($why);

            ok( $some_test );
            ok( $some_other_test );
        }

and write todo() the same way as before.  ok() would note that the
$Todo flag was set and act accordingly.  Problem is, I need to unset
that $Todo flag at the end of the block.  Can't think of a way to do
that.


-- 

Michael G. Schwern   <[EMAIL PROTECTED]>    http://www.pobox.com/~schwern/
Perl6 Quality Assurance     <[EMAIL PROTECTED]>       Kwalitee Is Job One
A tickle of paste
Teases down my sweaty thigh
Oh, plug it again!
        -- ignatz

Reply via email to