I had an idea yesterday.  On more than one occassion, a I've been asked
about running tests against a live site.  My usual waffle is to talk about
assertions or to build a seperate test suite which is explicitly non-modifying.
Or something Skud came up with which was to tag blocks of tests in the suite
as "modifying" and not run them against a live site.
That's always felt kind of artificial.  Tests are supposed to tell you
something's wrong.  Having to run a suite against a live site is more like
running the tests *after* you've found out something's wrong.  And then
I was thinking about inline testing, Test::Class and such and how it would
be nice if we could just write test functions right in our code, like
assertions.  Like Carp::Assert::More, but I want all the Test:: stuff
available.

I think this can be done with a simple Test::Builder subclass and
attribute changes.  Turn numbering off (since you don't know what order
they'll get run in, so its kind of meaningless, or if the thing will fork).  
Set no_plan, since the tests would come continuously.  Redirect output to a 
log file... and that should be it.  Then you can write:

    sub day_of_week {
        ...
        cmp_ok( $dow, '<=', 7 );
        cmp_ok( $dow, '>=', 1 );
        
        return $dow;
    }

Every time day_of_week() is run those two tests get run and go to a log file.

The only part missing is the ability to shut the tests off once you've
released it to production.  That's tricky.  The cheap way to do it is
what Carp::Assert uses, a constant.

    cmp_ok( ... ) if DEBUG;

Its wonky, but it works without fail.  Another way is to use a TEST: block
and have Filter::Simple strip them out.

    TEST: {
        cmp_ok( ... );
    }

Filtering makes me nervous, but the syntax is clean and the code will be
100% removed (at some startup cost).

Finally, there could be a TEST function which gets passed a subroutine
reference and use Sub::Uplevel to trick it into thinking its getting called
one level up...

    TEST {
        cmp_ok( ... );
    }

This'll work, but the TEST() function will always get called, even if its
just "return if $Not_Testing" that can get expensive in hot loops.

I could do all three. :)

Questions?  Comments?  Approval?


-- 
Beer still cheaper than crack!

Reply via email to