Andy Armstrong wrote: > On 27 Mar 2007, at 18:16, Gary Hawkins wrote: >> What about diag() output. > > It goes to STDERR and is therefore not really part of TAP. Many uses of > diag are expected to be replaced by the YAML based mechanism.
To expand on that, the plan is to transition test module authors away from using free-format diag() and using the structured YAML stuff instead. In general when a test module is using diag() they really want structured diagnostics anyway. As for users who use diag(), those messages do tend to really be free-form. For that diag() will start to use the proposed TAP logging syntax and no longer print to STDERR. http://testanything.org/wiki/index.php/TAP_logging_syntax diag() would be at the level "notice" and thus normally displayed. I'll probably add to Test::More an info() function which outputs at level "info" which is roughly the equivalent now to printing to STDOUT. Its not normally displayed. So, let's bring this together. A simple test like this: use File::Temp qw(tempfile); use Test::More tests => 3; is $dog, "Basset hound", "Basset hounds got long ears"; my($fh, $tmpfile) = tempfile(); print "# Using file $tmpfile\n"; ok( -w $tmpfile, "tmpfile is writable" ) or diag "$tmpfile not writable: $!"; ok( -x $tmpfile, "tmpfile is executable" ) or diag "$tmpfile not executable: $!"; Currently outputs this 1..3 not ok 1 - Basset hounds got long ears # Failed test 'Basset hounds got long ears' # at /Users/schwern/tmp/foo.t line 8. # got: 'Mutt' # expected: 'Basset hound' # Using file /tmp/HBN5dFYRBm ok 2 - tmpfile is writable not ok 3 - tmpfile is executable # Failed test 'tmpfile is executable' # at /Users/schwern/tmp/foo.t line 15. # /tmp/HBN5dFYRBm not executable: # Looks like you failed 2 tests of 3. And when run through Test::Harness it looks like this: $ prove ~/tmp/foo.t /Users/schwern/tmp/foo.... # Failed test 'Basset hounds got long ears' # at /Users/schwern/tmp/foo.t line 8. # got: 'Mutt' # expected: 'Basset hound' /Users/schwern/tmp/foo....NOK 1/3 /Users/schwern/tmp/foo....ok 2/3# Failed test 'tmpfile is executable' # at /Users/schwern/tmp/foo.t line 15. # /tmp/U2x9QTnKoL not executable: # Looks like you failed 2 tests of 3. /Users/schwern/tmp/foo....dubious Test returned status 2 (wstat 512, 0x200) DIED. FAILED tests 1, 3 Failed 2/3 tests, 33.33% okay Failed Test Stat Wstat Total Fail List of Failed ------------------------------------------------------------------------------- /Users/schwern/tmp/foo.t 2 512 3 2 1 3 Failed 1/1 test scripts. 2/3 subtests failed. Files=1, Tests=3, 0 wallclock secs ( 0.05 cusr + 0.01 csys = 0.06 CPU) Failed 1/1 test programs. 2/3 subtests failed. A bit messy. Since all the failure diagnostics are going to STDERR Test::Harness can't format their output or control it or be aware of it at all. So its a mess. They're also unparsable. Nobody but a human can say why the tests failed. The next gen TAP using the same code, except the print to STDOUT replaced with an info() call, will look something like this. TAP version 16 --- datetime: Tue, 27 Mar 2007 15:56:58 -0700 file: /Users/schwern/tmp/foo.t hostname: windhund.schwern.org producer: name: Test::Builder version: 0.72 ... 1..3 not ok 1 - Basset hounds got long ears --- line: 8 code: 'is $dog, "Basset hound", "Basset hounds got long ears";' got: 'Mutt' expected: 'Basset hound' display: |2 got: 'Mutt' expected: 'Basset hound' ... **info** Using file /tmp/HBN5dFYRBm ok 2 - tmpfile is writable --- line: 12 code: ok( -w $tmpfile, "tmpfile is writable" ) ... not ok 3 - tmpfile is executable --- line: 15 code: ok( -x $tmpfile, "tmpfile is executable" ) ... **notice** /tmp/HBN5dFYRBm not executable: **fail** Looks like you failed 2 tests of 3. This incorporates these three proposals as well as the new version syntax which has been accepted. http://testanything.org/wiki/index.php/Test_meta_information http://testanything.org/wiki/index.php/TAP_diagnostic_syntax http://testanything.org/wiki/index.php/TAP_logging_syntax The amount of information to put in the YAML is up to the TAP producer, all of the keys are optional as is outputting any YAML at all. This example is probably about the level of default verbosity I'd expect. The "display" key is just a suggestion to the TAP producer about how to display the failure. The "code" key is an example of extra information it will be possible for a producer to send on to the parser. The parser will then choose what to do with it. So the raw test output is a little more verbose than before and possibly a little harder for a human to read. But now its all in one stream (STDOUT) and all parsed by the parser. We trade off a little verbosity and a little human readability of the raw stream for a much more flexible TAP display. A hypothetical display might look like this: $ prove3 ~/tmp/foo.t Running /Users/schwern/tmp/foo....1/3 ------------------------------------------------------- !!!! Failed test #1: 'Basset hounds got long ears' !!!! !!!! at /Users/schwern/tmp/foo.t line 8. !!!! !!!! code: 'is $dog, "Basset hound", "Basset hounds got long ears";' !!!! actual: 'Mutt' !!!! !!!! expected: 'Basset hound' !!!! ------------------------------------------------------- ...........................3/3 ------------------------------------------------------- !!!! Failed test #3: 'tmpfile is executable' !!!! !!!! at /Users/schwern/tmp/foo.t line 15. !!!! !!!! code: 'ok( -x $tmpfile, "tmpfile is executable" )' ------------------------------------------------------- [notice] /tmp/U2x9QTnKoL not executable: [fail] Looks like you failed 2 tests of 3. Test returned status 2 (wstat 512, 0x200) DIED. FAILED tests 1, 3 Failed 2/3 tests, 33.33% okay Failed Test Stat Wstat Total Fail List of Failed ------------------------------------------------------------------------------- /Users/schwern/tmp/foo.t 2 512 3 2 1 3 Failed 1/1 test scripts. 2/3 subtests failed. Files=1, Tests=3, 0 wallclock secs ( 0.05 cusr + 0.01 csys = 0.06 CPU) Failed 1/1 test programs. 2/3 subtests failed. Not terribly imaginative, I admit, but still much improved readability. This is possible because the displayer has full control over all the diagnostics. It can parse and reformat them as it likes. Everything in the example above is printed by the parser. Nothing comes directly from the producer. Its not a mistake that a changed the "got" key to "actual" as some people have requested. The parser can accept flags to display information about passing tests, show different levels of logs, be very quiet, be very verbose, put it all into a file, translate it to XML, send it out via email... sky's the limit. Folks who do more radical things like TAP::HTML::Matrix (which is radical only in a relative sense) will find this new syntax extremely useful as they can now archive and display all the same information you get by running a test on the terminal. They no longer have to scrape things like file and line number out of the diagnostics.