The pragma is 'stop_testing'.  

The test script that deals with the issue is t/babel.000.reqs.t.  Near the top, 
the scripts says
        print "TAP version 13\n";

The script then checks that certain essential modules can be loaded - 
Class::AutoDB, DBI, DBD::mysql.  For reasons I don't understand, despite being 
listed in the 'build_requires' section of Build.PL, Build tries to do the build 
even when these prerequisites are not met. 

Finally the script tries to connect to MySQL and do the necessary 
manipulations.  

If any of the checks fail, the script constructs a detailed diagnostic message 
and prints it by saying
          diag($diag);
Then it prints the pragma:
        print "pragma +stop_testing\n";

The TAP parser processes the pragma and makes this information available to the 
harness.  The code that handles the pragma is in my customized version of 
run_tap_harness in t/Build.pm.   The main part of run_tap_harness is a loop 
that runs each test script.  At the end of each iteration, ie, after running 
each test script, the code says
    my @parsers=$agg->parsers;
    my $parser=$parsers[$#parsers];
    my @pragmas=$parser->pragmas;
    last if grep /stop_testing/i,@pragmas;

This reaches into the TAP aggregator (the aggregator collects results from 
compound tests - not relevant here) to get the list of parsers that were 
created to parse the test results - here there will only be one, but I wrote 
the code for the general case.  Then it grabs the last parser and gets the list 
of pragmas processed by the parser - again there will only be one, but I wrote 
the code for the general case.  If one of the pragmas was stop_testing, it 
breaks out of the loop and the test suite comes to a halt.

This is not the only way one could solve the problem.  Instead of using the 
pragma mechanism (some might say 'mis-using' since stop_testing is really a 
directive not a pragma in the proper sense), one could invent a new kind of TAP 
message and create a TAP parser subclass to process the message.   The TAP 
design envisions this sort of customization and it wouldn't be too hard.  I 
chose to go the pragma route because it was a bit simpler for my limited 
purpose.

What are you trying to do?  Are you looking for a way to check that MySQL is 
available, or are you thinking about using the pragma mechanism for something 
else?

Best,
Nat

On Aug 9, 2013, at 5:01 AM, Steffen Schwigon wrote:

> Hi!
> 
> And what particular pragma did you invent, when is it generated, how
> does it influence the TAP parsing with the particular "MySQL
> unavailable" isse?
> 
> Thanks.
> 
> Kind regards,
> Steffen
> 
> "Nathan (Nat) Goodman" <ngood...@systemsbiology.org> writes:
>> Hi Steffen
>> 
>> TAP as you probably know is a line-oriented protocol whose main purpose it 
>> to let test scripts communicate pass/fail results to a test harness.  
>> Functions like 'ok' or 'pass' or 'fail' in Test::More print lines that tell 
>> the harness whether a test passed or failed. 
>> 
>> The main TAP site is http://testanything.org/.  The TAP specification is at 
>> http://podwiki.hexten.net/TAP/TAP.html?page=TAP
>> 
>> I learned about TAP pragmas by reading the TAP CPAN documentation and code, 
>> esp. TAP::Parser , 
>> http://search.cpan.org/~ovid/Test-Harness-3.28/lib/TAP/Parser.pm#pragmas
>> 
>> To make it work you have to tell the TAP harness that you're using TAP 
>> version 13, whose specification is at 
>> http://podwiki.hexten.net/TAP/TAP13.html?page=TAP13
>> 
>> You do this from a test script  by printing this line  
>>      TAP version 13
>> 
>> The format of a pragma is    pragma +/-<whatever>, eg,
>>      pragma +strict
>> 
>> The + or - is mandatory!
>> 
>> To process a non-standard pragma, you have to customize some aspect of the 
>> test harness.  I did this by creating a subclass of Module::Build which I 
>> needed for other purposes anyway.  The subclass is in the Data::Babel 1.12 
>> distribution, file t/Build.pm.  You also have to tell the main Build driver 
>> to use the subclass.  This is in Build.PL; the relevant few lines of code 
>> are near the top
>> 
>>      use lib qw(t);
>>      use t::Build;                   # my Module::Build subclass
>>      my $class='t::Build';
>> 
>> followed a few lines later by 
>> 
>>      my $builder = $class->new
>>      ....
>> 
>> I hope this helps.  Feel free to ask for further clarification as necessary. 
>>  I'm glad to help. 
>> 
>> Best,
>> Nat
>> 
>> On Aug 6, 2013, at 3:51 AM, Steffen Schwigon wrote:
>> 
>>> "Nathan (Nat) Goodman" <ngood...@systemsbiology.org> writes:
>>>> 3) What I ended up doing with Data::Babel (and will do with
>>>> Class:AutoDB soon) is to move the check for MySQL into a test script
>>>> that runs first. If the script detects that MySQL is unavailable, it
>>>> reports this to the test driver using the pragma capability of TAP
>>>> version 13, and a slightly customized version of
>>>> Build::run_tap_harness (included in my distribution) breaks out of the
>>>> test suite when it sees this pragma, reporting PASS as the outcome.
>>> 
>>> Can you please elaborate more on the details of your pragma solution. 
>>> 
>>> I never saw a TAP pragma in real world[1] and would love to understand
>>> it - without reading into your code, sorry for that laziness... :-)
>>> 
>>> Kind regards,
>>> Steffen
>>> 
>>> Footnotes: 
>>> [1]  except that I support highlighting it in Emacs TAP mode
>>> -- 
>>> Steffen Schwigon <s...@renormalist.net>
>> 
> 
> -- 
> Steffen Schwigon <s...@renormalist.net>

Reply via email to