That was a terrific eplanation and I thank you for taking the time to explain. 
Much appreciated.
Sent via BlackBerry from T-Mobile

-----Original Message-----
From: Michael G Schwern <schw...@pobox.com>

Date: Fri, 23 Jan 2009 20:48:57 
To: <rf...@drivebuytech.com>
Cc: David E. Wheeler<da...@kineticode.com>; Eric 
Wilhelm<scratchcomput...@gmail.com>; <perl-qa@perl.org>
Subject: Re: numeric plans - feature or symptom?


rf...@drivebuytech.com wrote:
> Late to this discussion. But can somebody explain to me why in java or .net 
> or groovy or
> ruby a programmer doesn't have to induicate the number of tests that will
run before hand
> but in perl he must?

Let's make something clear, Perl says nothing about this.  This is TAP, a
cross-language testing protocol which you can use in Java or .Net or Groovy or
Ruby or whatever.  Similarly, you can use xUnit style tests in Perl (see
Test::Unit, but really don't).


Short answer:  Ask Larry.  He put it there 20 years ago.

The plan does two things:  First, it defends against premature test exits.
Since premature exit usually means it crashed, we can check the exit code of a
test this isn't so important any more.

Second, and more importantly, the plan allows you to test for things which
*don't* happen.

Consider the following

    print "1..2\n";
    if( fork ) {
        print "ok\n";
    }
    else {
        print "ok\n";
    }

Consider the case where the fork() succeeds but the child process does not
run.  The result will be:

1..2
ok

All tests pass, but the plan is violated so it's a failure.  Without a plan
this sort of thing is more difficult to catch.

Another example might be this:

    $thing->add_event_handler( Ping => sub { print "ok\n" } );

Let's say you expect $thing to handle three and only three Ping events.  You
can plan for that.  You can plan for not getting a ping event or getting too
many ping events.  Without the plan this would be more difficult to handle,
you'd have to do the event counting yourself.  In the fork() case you'd have
to implement some sort of interprocess communication.  No fun.

OTOH Java does a lot of threaded code so they must have some way to deal with
this better than I think they do.  I'm no xUnit expert.


In reality, most of this kerfuffery about plans goes away once Test::Builder
stops bitching when you try to run a test before declaring a plan.  The
"deferred plan".  It allows a lot more flexibility in planning and a safer
no_plan.


As for xUnit vs TAP, it comes down to this:  in xUnit the code being tested
and the test runner are all wrapped up in the same process.  In TAP they are
not.  This has its ups and downs.

There is another key difference.  In xUnit, when you fail an assert you stop
the test.  A passing test is one that doesn't halt.  This is because xUnit has
the philosophy that any data after a failing test is suspect, so why bother?
In TAP we like to keep going, because that data after the fail might be useful
and it would suck not to have it.  TAP doesn't dictate this, but that's how
TAP tests tend to be written.

In xUnit a passing test suite is simply one that has no failing tests.  TAP is
a little more stringent.  A passing test suite must have no failing tests AND
must conform to the plan.  This lets you test some otherwise difficult cases
seen above.

Anyhow, because a TAP parser is reading results from another process, and
because it has little control over that process, it needs some more
information to know that things went ok.  If the test crashes, or exits
prematurely, but all tests up to that point passed it needs to know that.  In
xUnit if the test crashes your whole test runner crashes.

But these days a TAP parser can catch most premature exits by just looking at
the exit code of the test, so the plan is less useful than it once was.


-- 
Don't try the paranormal until you know what's normal.
    -- "Lords and Ladies" by Terry Prachett

Reply via email to