I'm writing test a test module and naturally I want to test it. 2 minutes ago 
I discovered Test::Builder::Tester but before finding that I spent several 
hours inventing a slightly different wheel... twice.

The result is Test::Tester 

http://www.fergaldaly.com/computer/Test-Tester/

It's not complete but I think it advantages over Test::Builder::Tester. It's 
easier to use because you don't have to worry so much about predicting the 
textual output of your tests and getting the numbering right.

I'm not that happy about either of my implementations and I'm looking for 
suggestions. First an example

If you have a string comparison test called is() then you can do

check_test(
  sub { is("this", "this", "eq") },
  {
    name => 'eq',
    ok => 1,
    diag => "",
  },
  "eq",
);

check_test(
  sub { is("this", "that", "not eq") },
  {
    name => 'not eq',
    ok => 0,
    diag => <<EOM,
         got: 'this'
    expected: 'that'
EOM
  },
  "not eq",
);

which will give
ok 1 - Test 'eq' completed
ok 2 - Test 'eq' result count
ok 3 - subtest 'eq' of 'eq' correct result
ok 4 - subtest 'eq' of 'eq' correct name
ok 5 - subtest 'eq' of 'eq' correct diag
ok 6 - Test 'not eq' completed
ok 7 - Test 'not eq' result count
ok 8 - subtest 'not eq' of 'not eq' correct result
ok 9 - subtest 'not eq' of 'not eq' correct name
ok 10 - subtest 'not eq' of 'not eq' correct diag

There are 2 ways to get this. Both of them are ugly.

Way 1: You have to first force your test module to use Test::Tester's 
capturing object instead of the standard Test::Builder one, not so difficult, 
since it's your test module, you can arrange for a set_builder function or 
somesuch.

Now that the Test::Builder object has been replaced by a Test::Tester::Capture 
object, we can capture all the oks, diags etc from your module and make sure 
that they're correct.

The problem is that it's a bit messy, it requires your module to let your test 
script replace it's Test::Builder object. It also requires me to think about 
when does one test start and another finish and also to reimplement various 
bits of Test::Builder's details() functionality.

Way 2: Just call Test::Tester::fh() at the start of the script and it will use 
Test::Builder's output capture stuff to get all the diags and match them up 
with the results from details(). This is nicer in some ways but it does a lot 
of fiddling around with Test::Builder's current_test() and details() which 
results in bugs summaries at the end of your scripts and sometimes some 
rather alarming messages about contacting the author (as evidenced by a make 
test).

I think these problems can be resolved without drastic changes, I just need a 
way of saving and restoring @Test_Details but it's still a bit messy 
examining the failure output, maybe a specific diag_output filehandle is 
needed too.

Another way to do it might be to allow 2 Test::Builder objects. Leave the 
existing interface as it is, Test::Builder->new still returns the same object 
every time but add a new constuctor new_meta which turns off output from the 
first and returns a second Test::Builder object. The module to be tested uses 
the silent Test::Builder and the test script uses the the one that came from 
new_meta. This involves large changes to Test::Builder. So it's probably not 
an option.

Any comments or suggestions?

F

-- 
Do you need someone with lots of Unix sysadmin and/or lots of OO software 
development experience? Go on, giz a job.
My CV - http://www.fergaldaly.com/cv.html

Reply via email to