In my application I may have to parse from a stream of TAP produced by more than one test set. In looking around for prior work in that area, I found TAP::Stream and a message from someone working on Plan 9.
It would be nice to have a parse method that either returns a list of TestSet, or invokes a callback once for each TestSet when it comes out of the oven. It looks like TAP::Stream builds an über-testset with each set that it parsed as a subtest, though I've only glanced at it so I might not be right about that. In any case, even if tap4j's parser just returned a list or used a callback, it would be easy to build the rest of that on it.
The API as it stands is not so easy to build upon, because after seeing some input that probably means a new test set started, the caller can't easily get the preceding TestSet (an exception is thrown instead of returning it), and some of the next one has already been read from the stream, so unless the caller knows how much to push back, it isn't easy to start a new Parser to parse the next part.
It seems like the signs for one TestSet to come out of the oven would include:
- seeing another TAP header
- seeing another plan (if the prior one was beforeTestResult)
- seeing anything after a plan that wasn't beforeTestResult (except maybe a footer)
- seeing anything after a TAP footer
(By the way, what is a TAP footer? I see no mention in the spec here, is there a newer version I should be looking at?)
Those are the rules that pop into my head, though it might be better to try to match exactly what something else is doing, like TAP::Stream.
I ny my application, I might try to just put something in front of the parser that would try to match those events in the stream and feed the lines to a succession of parsers, but that has the code-duplication disadvantage of having to check for some of the exact same patterns the Parser already knows about.
and whatever I do there will probably be stupid about stuff in a YAML stream that looks like a TAP line, etc.) So it seems like really it should be in the parser and done right.
If the onPlan/onTestResult/etc. methods were virtual, a caller might be able to subclass the parser and get the wanted behavior by overriding some of them (it would start to look like SAX then), but they're currently private so that's not an option.