# 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
---------------------------------------------------