On 2012.7.11 2:39 PM, Daniel Perrett wrote: > I may have missed the point here, but would it be sufficient to have > two flavours of diagnostic calls, distinguishing between pre-test > diagnostics (`forewarn()`) and post-test diagnostics (`reflect()`), or > is the problem that ok() must be a single function call?
Rather than tell you what I think the solution should be, let me frame the problem. I'm going to use a fictional XML format for illustration, but the problem applies to a broad class of formats which are different than TAP. Consider this test... #line 12 ok( 0, "something" ); and the output in our fictional XML format might look like this... <result> <status>fail</status> <name>something</name> <line>12</line> </result> The important thing to note is that the result has a clear start and end. Now, if all information about a result has to go inside the <result> tag, how does this code... #line 12 ok( 0, "something" ); info( { have => "this", want => "that" } ); Know to produce this output... <result> <status>fail</status> <name>something</name> <line>12</line> <attr key="have">this</attr> <attr key="want">that</attr> </result> ...and yet still work when there is no tap_diag() call after the ok()? There are a number of alternative interfaces to solve the problem. Making each assert a single function call is the "best" from the point of view of ease of formatting, but requires every assert to take an extra argument. I feel this is getting bulky from an interface perspective, but maybe it's ok. ok( 0, "something", { have => "this", want => "that" }); Another one would be to turn results into objects and only format when they go out of scope... ok( 0, "something" )->info({ have => "this", want => "that" }); ...but that goes pear shaped if somebody does this. $results{$test} = is( $this, $that ); You could do some clever tricks where the formatter waits until the next result to display a result, in case extra info comes in. # store the result. ok( 0, "something" ); # attach this to the previous result. info( { have => "this", want => "that" } ); # format and display the previous result and info. # store this result. ok( 0, "something else" ); # format and display the previous result with no extra info. # store this result. ok( 0, "something more" ); # format and display the previous result. # end the test. done_testing(); ...but that significantly complicates the formatters and puts streamed output on a delay. Very confusing if you're stepping through the code. Right now the "all in one" version seems best. It's explicit. It's simple. > If that's possible, maybe we can extend it to guess at what the > various messages mean: most diags can be assumed to be of the > `reflect()` type, as that's typical behaviour, e.g. Test::More, while > more perlish warnings is most likely to be of the `forewarn()` > variety. I think we don't have to guess at that. Structured diagnostics are only associated with test results (and possibly start/end of test info). They're not used like diag() is now as both a warning mechanism and a test result information system. Since this is a new interface, we can deal with that by making different functions for each different intent. One for "this goes with the previous result". One for "this is general test information". And one for "this is just a diagnostic dump for and not associated with anything". -- You know what the chain of command is? It's the chain I go get and beat you with 'til you understand who's in ruttin' command here. -- Jayne Cobb, "Firefly"