# from Ovid
# on Thursday 22 January 2009 15:01:

>For example, with your code (as I understand it):
>
>  test {
>      my $manager = Feed::Manager->new($some_uri);
>      foreach my $resource ($manager->resources) {
>          ok my $result = $manager->get($resource), "$resource should
> work"; }
>  }
>
>Imagine that the Feed::Manager connects to an outside resource I don't
> have control over and one day they add a new resource.  I now have a
> new test and need to know that something has changed.

What is it that you need to know in this case?  That resources() is 
returning a new value?  If $manager->get($resource) worked, do you need 
to know that there are more?

If so, you're using the plan as something like a stand-in for the 
assertion:

  my @resources = $manager->resources;
  is(scalar(@resources), 12, "have 12 resources");

And actually, you probably want to assert something like:

  my @resources = $manager->resources;
  is_deeply([sort(@resources)], \...@expect_resources);

Which fails more descriptively than a plan failure.

But all this test() function does -- accounting for perl 5 
limitations -- is to run a block of who-cares-how-many assertions and 
guarantee that the block returns.  It only emulates is_deeply() in that 
regard (and without messing with tap it would simply emit a single ok.)

A function which takes a list would be a different thing.

  test_list(\...@resources, sub {
    my $resource = shift;
    ok my $result = $manager->get($resource), "$resource should work"; }
  });

And this, too, could be fully planned before running by ending with 
now_run_them() sort of a thing.

Or, again with the details:  perhaps a pre-pass would cripple the test() 
and test_list() &c functions to merely *count* their number (and number 
of arguments).  One could then hard-code an assertion into the top of 
the file.

As for skipping and todoing -- the block control is now owned by the 
function rather than the interpreter root.  One could even have a set 
of test {} calls within a block where the skip setting merely instructs 
the test calls to not execute their blocks.  In which case you wouldn't 
have to count the number of tests being skipped.  (But you would have 
to ensure that your code-to-skip gets inside the blocks -- because 
everything has trade-offs.)

This does reverse the ownership of control flow.  So, I guess I'm 
basically saying that you simply need to code your tests in a purely 
functional way to avoid the halting problem.  A quick review of S04 
doesn't seem to say that we're getting much to do with introspecting 
blocks, but I'm pretty sure Perl 6 will allow us to declare subroutines 
which take blocks and lists (or iterators) with less hassle than Perl 5

And yes, iterators reintroduce the halting problem because everything 
has trade-offs.  Nonetheless, you can still magically deduce that we're 
done_testing() because if any test{} didn't return we hit exit() or 
whatever in the middle.  You can also potentially produce some 
semblance of a progress report.

I don't know if this all means that you need nested tap, or even Perl 6.  
I do hope it points to what might be possible and even maybe relatively 
easy.

Certainly, I find that the numeric plan is clunky and no_plan is too 
unguarded.  The done() is a step.  The numeric plan is not strictly 
necessary and I think any assertion it performs can be achieved (with 
better diagnostics) by actually asserting that what you intend to do is 
done as intended.  Maybe that logical transformation from one number to 
@things and @stuff is not for everyone or is considered overly 
prescriptive, but there's more than one way to do it and perhaps even 
three.

--Eric
-- 
"It is a mistake to allow any mechanical object to realize that you are 
in a hurry."
--Ralph's Observation
---------------------------------------------------
    http://scratchcomputing.com
---------------------------------------------------

Reply via email to