I just wanted to bring up nested blocks and sub-plans again. I've been hacking
around in Test::Builder and I've implemented something that works and does
something that I think is useful. It allows you to write tests that have
output like
1..5
ok 1 - pass
ok 2 - fail
1..3 a nested set of tests
ok 1 - some test
ok 2 - some other test
1..2 and another layer
ok 1 - more tests
ok 2 - another
ok 3 - block 'an another layer'
ok 3 - block 'a nested set of tests'
ok 4 - pass
ok 5 - fail
each sub block has it's own plan and the numbering starts from 1. When working
out the plan for a block, you don't need to think about what happens inside
it's sub blocks. This makes planning very easy.
When each block finishes it will test that the plan was followed.
Tarball is at
http://www.fergaldaly.com/computer/Test-Builder/
Why would you want to do this? Simple example.
use Test::More tests => 3;
use MyCompany;
is_valid_person(get_manager(), "manager");
is_valid_person(get_ceo(), "ceo");
is_valid_person(get_secretary(), "sec");
sub is_valid_person
{
my $person = shift;
my $name = shift;
my $block = Test::Builder::block("$name valid person?", tests => 17);
isa($item, "Person", "is a person?");
like($item->name, qr/^\w+\s+\w$/, "std name");
# 15 more tests
}
The plan says 3 tests even though there are 3x17 = 34 tests but because the
is_valid_person tests run in a sub block, they count as just 1 test and if we
add a new test to that subroutine we just have to update the sub plan, not
the main one. Also if we call is_valid_person() again, we just increase the
main plan by 1, not by 17.
So now you can have structured programming in test scripts.
The output above is compatible with Test::Harness because TH ignores lines
beginning with whitespace. If a test fails inside a sub block, the error will
propogate all the way to the outermost block so TH will see it. So you can
test this out without modifying TH, although it would be nice if TH
understood this format.
This was implemented in 2 stages. First Test::Builder was changed to store
it's state in a hash instead of package lexicals. Then I added some methods
to create blocks and track them. You can see the 2 patches at the above URL.
I also knocked out thread safety because it was bugging me with strange
errors. The whole nested blocks thing will never work nicely with threads
anyway and since this is just proof of concept it's not too important for
now.
Comments? Suggestions? Any chance you would consider this Michael?
F