1 | # tap-parser
|
2 |
|
3 | parse the [test anything protocol](http://testanything.org/)
|
4 |
|
5 | [![build status](https://secure.travis-ci.org/tapjs/tap-parser.png)](http://travis-ci.org/tapjs/tap-parser)
|
6 |
|
7 | [![browser support](http://ci.testling.com/substack/tap-parser.png)](http://ci.testling.com/substack/tap-parser)
|
8 |
|
9 | [![coverage status](https://coveralls.io/repos/tapjs/tap-parser/badge.svg?branch=master&service=github)](https://coveralls.io/github/tapjs/tap-parser?branch=master)
|
10 |
|
11 | # example
|
12 |
|
13 | ``` js
|
14 | var Parser = require('tap-parser');
|
15 | var p = new Parser(function (results) {
|
16 | console.dir(results);
|
17 | });
|
18 |
|
19 | process.stdin.pipe(p);
|
20 | ```
|
21 |
|
22 | given some [TAP](http://testanything.org/)-formatted input:
|
23 |
|
24 | ```
|
25 | $ node test.js
|
26 | TAP version 13
|
27 | # beep
|
28 | ok 1 should be equal
|
29 | ok 2 should be equivalent
|
30 | # boop
|
31 | ok 3 should be equal
|
32 | ok 4 (unnamed assert)
|
33 |
|
34 | 1..4
|
35 | # tests 4
|
36 | # pass 4
|
37 |
|
38 | # ok
|
39 | ```
|
40 |
|
41 | parse the output:
|
42 |
|
43 | ```
|
44 | $ node test.js | node parse.js
|
45 | { ok: true, count: 4, pass: 4, plan: { start: 1, end: 4 } }
|
46 | ```
|
47 |
|
48 | # usage
|
49 |
|
50 | This package also has a `tap-parser` command.
|
51 |
|
52 | ```
|
53 | Usage:
|
54 | tap-parser <options>
|
55 |
|
56 | Parses TAP data from stdin, and outputs the parsed result
|
57 | in the format specified by the options. Default output is
|
58 | uses node's `util.format()` method.
|
59 |
|
60 | Options:
|
61 |
|
62 | -j [<indent>] | --json[=indent]
|
63 | Output event data as JSON with the specified indentation (default=2)
|
64 |
|
65 | -t | --tap
|
66 | Output data as reconstituted TAP based on parsed results
|
67 |
|
68 | -l | --lines
|
69 | Output each parsed line as it is recognized by the parser
|
70 |
|
71 | -b | --bail
|
72 | Emit a `Bail out!` at the first failed test point encountered
|
73 |
|
74 | -w | --ignore-all-whitespace
|
75 | Skip over blank lines outside of YAML blocks
|
76 |
|
77 | -o | --omit-version
|
78 | Ignore the `TAP version 13` line at the start of tests
|
79 | ```
|
80 |
|
81 | # methods
|
82 |
|
83 | ``` js
|
84 | var Parser = require('tap-parser')
|
85 | ```
|
86 |
|
87 | ## var p = new Parser(options, cb)
|
88 |
|
89 | Return a writable stream `p` that emits parse events.
|
90 |
|
91 | If `cb` is given it will listen for the `'complete'` event.
|
92 |
|
93 | If `options` is given, it may contain the following flags:
|
94 |
|
95 | - `preserveWhitespace` boolean which is `false` by default and will
|
96 | cause the parser to emit `line` events even for lines containing
|
97 | only whitespace. (Whitespace lines in yaml blocks are always
|
98 | emitted, because whitespace is semantically relevant for yaml.)
|
99 |
|
100 | - `strict` boolean which is `false` by default and causes the parser
|
101 | to treat non-TAP input as a failure. Strictness is heritable to
|
102 | child subtests. You can also turn strictness on or off by using the
|
103 | `pragma +strict` line in the TAP data to turn strictness on, or
|
104 | `pragma -strict` to turn strictness off.
|
105 |
|
106 | - `bail` boolean which is `false` by default and will cause the parser
|
107 | to bail out (including emitting a synthetic `Bail out!` line)
|
108 | whenever a failed test point is encountered.
|
109 |
|
110 | - `omitVersion` boolean which is `false` by default and will cause the
|
111 | parser to ignore `TAP version 13` lines. Version lines in subtests
|
112 | cause problems with some parsers, so they are always ignored.
|
113 |
|
114 | - `passes` boolean which is false by default and will add "passes" property for that contains the result of all passed tests
|
115 |
|
116 | The `parent`, `level` and `buffered` options are reserved for internal
|
117 | use.
|
118 |
|
119 | # events
|
120 |
|
121 | ## p.on('complete', function (results) {})
|
122 |
|
123 | The `results` object contains a summary of the number of tests
|
124 | skipped, failed, passed, etc., as well as a boolean `ok` member which
|
125 | is true if and only if the planned test were all found, and either
|
126 | "ok" or marked as "TODO".
|
127 |
|
128 | ## p.on('line', function (line) {})
|
129 |
|
130 | As each line of input is parsed, a `line` event is emitted.
|
131 |
|
132 | "Synthetic" line events will be emitted to support the `bail`
|
133 | behavior, and to inject `1..0` plan lines in subtests that have no
|
134 | test points. They can be used as a sort of "passthrough stream" to
|
135 | sanitize and filter a TAP stream, with the caveat that, while `line`
|
136 | events will be semantically equivalent to the TAP input, they will not
|
137 | be a perfect replica of the input.
|
138 |
|
139 | ## p.on('assert', function (assert) {})
|
140 |
|
141 | Every `/^(not )?ok\b/` line will emit an `'assert'` event.
|
142 |
|
143 | Every `assert` object has these keys:
|
144 |
|
145 | * `assert.ok` - true if the assertion succeeded, false if failed
|
146 | * `assert.id` - the assertion number
|
147 | * `assert.name` - optional short description of the assertion
|
148 |
|
149 | and may also have
|
150 |
|
151 | * `assert.todo` - optional description of why the assertion failure is
|
152 | not a problem. (Boolean `true` if no explaination provided)
|
153 | * `assert.skip` - optional description of why this assertion was
|
154 | skipped (boolean `true` if no explanation provided)
|
155 | * `assert.diag` - a diagnostic object with additional information
|
156 | about the test point.
|
157 |
|
158 | ## p.on('comment', function (comment) {})
|
159 |
|
160 | Every `/^# (.+)/` line will emit the string contents of `comment`.
|
161 |
|
162 | ## p.on('plan', function (plan) {})
|
163 |
|
164 | Every `/^\d+\.\.\d+/` line emits a `'plan'` event for the test numbers
|
165 | `plan.start` through `plan.end`, inclusive.
|
166 |
|
167 | If the test is [completely
|
168 | skipped](http://podwiki.hexten.net/TAP/TAP.html?page=TAP#Skippingeverything)
|
169 | the result will look like
|
170 |
|
171 | ```
|
172 | { ok: true,
|
173 | count: 0,
|
174 | pass: 0,
|
175 | plan:
|
176 | { start: 1,
|
177 | end: 0,
|
178 | skipAll: true,
|
179 | skipReason: 'This code has no seat belt' } }
|
180 | ```
|
181 |
|
182 | ## p.on('version', function (version) {})
|
183 |
|
184 | A `/^TAP version (\d+)/` line emits a `'version'` event with a version
|
185 | number or string.
|
186 |
|
187 | ## p.on('bailout', function (reason) {})
|
188 |
|
189 | A `bail out!` line will cause the parser to completely stop doing
|
190 | anything. Child parser bailouts will bail out their parents as well.
|
191 |
|
192 | ## p.on('child', function (childParser) {})
|
193 |
|
194 | If a child test set is embedded in the stream like this:
|
195 |
|
196 | ```
|
197 | TAP Version 13
|
198 | 1..2
|
199 | # nesting
|
200 | 1..2
|
201 | ok 1 - true is ok
|
202 | ok 2 - doag is also okay
|
203 | ok 1 - nesting
|
204 | ok 2 - second
|
205 | ```
|
206 |
|
207 | then the child stream will be parsed and events will be raised on the
|
208 | `childParser` object.
|
209 |
|
210 | Since TAP streams with child tests *must* follow child test sets
|
211 | with a pass or fail assert based on the child test's results, failing
|
212 | to handle child tests should always result in the same end result.
|
213 | However, additional information from those child tests will obviously
|
214 | be lost.
|
215 |
|
216 | See `Subtests` below for more information on which sorts of subtest
|
217 | formats are supported by this parser.
|
218 |
|
219 | ## p.on('extra', function (extra) {})
|
220 |
|
221 | All other lines will trigger an `'extra'` event with the line text.
|
222 |
|
223 | # install
|
224 |
|
225 | With [npm](https://npmjs.org) do:
|
226 |
|
227 | ```
|
228 | npm install tap-parser
|
229 | ```
|
230 |
|
231 | You can use [browserify](http://browserify.org) to `require('tap-parser')` in
|
232 | the browser.
|
233 |
|
234 | # license
|
235 |
|
236 | MIT
|
237 |
|
238 | # subtests
|
239 |
|
240 | 5 flavors of Subtests are suppored by this parser.
|
241 |
|
242 | 1. Unadorned.
|
243 | Indented TAP data with no comment, followed by a test
|
244 | point at the parent level.
|
245 |
|
246 | ```
|
247 | ok 1
|
248 | 1..1
|
249 | ok 1 - child test
|
250 | 1..1
|
251 | ```
|
252 |
|
253 | 2. Indented comment.
|
254 | An indented `# Subtest: <name>` comment, followed by indented TAP
|
255 | data, and then a not-indented test point with a matching name.
|
256 | The summary test point may have yaml diagnostics.
|
257 |
|
258 | ```
|
259 | # Subtest: child test
|
260 | ok 1
|
261 | 1..1
|
262 | ok 1 - child test
|
263 | 1..1
|
264 | ```
|
265 |
|
266 | 3. Unindented comment.
|
267 | A not-indented `# Subtest: <name>` comment, followed by indented TAP
|
268 | content, followed by a test point with a matching name.
|
269 | The summary test point may have yaml diagnostics.
|
270 |
|
271 | ```
|
272 | # Subtest: child test
|
273 | ok 1
|
274 | 1..1
|
275 | ok 1 - child test
|
276 | 1..1
|
277 | ```
|
278 |
|
279 | 4. Buffered, without diagnostics.
|
280 | A test point line ending in {, followed by indented TAP content, ended
|
281 | with a } to close the block. todo/skip directives may come *either*
|
282 | before or after the `{` character. Yaml diagnostics are not allowed.
|
283 |
|
284 | ```
|
285 | ok 1 - child test {
|
286 | ok 1
|
287 | 1..1
|
288 | }
|
289 | 1..1
|
290 | ```
|
291 |
|
292 | 5. Buffered, with diagnostics.
|
293 | A test point line with yaml diagnostics, followed by `{` alone on a
|
294 | line, indented TAP data, and then a `}`.
|
295 |
|
296 | ```
|
297 | ok 1 - child test
|
298 | ---
|
299 | some: diagnostic
|
300 | data: true
|
301 | ...
|
302 | {
|
303 | ok 1
|
304 | 1..1
|
305 | }
|
306 | ```
|
307 |
|
308 | In all cases, the parsed behavior is identical:
|
309 |
|
310 | 1. The parent emits a `child` event with the `childParser` as an
|
311 | argument.
|
312 | 2. The `childParser` emits a `comment` with `# Subtest: <name>` (or
|
313 | `(anonymous)` for Unadorned subtests.)
|
314 | 3. When the test is over, the closing test point is emitted on parent
|
315 | test.
|
316 |
|
317 | That is, buffered and nonindented/indented comment subtests are parsed
|
318 | as if they are identical input, since their semantics are the same. This
|
319 | simplifies implementation of test harness and reporter modules.
|
320 |
|
321 | Since unadorned subtests have no introduction, a child event is not
|
322 | emitted until the first "relevant tap" line is encountered. This can
|
323 | cause confusion if the test output contains a spurious " 1..2" line
|
324 | or something, but such cases are rare.
|
325 |
|
326 | Similarly, this means that a test point ending in `{` needs to wait to
|
327 | emit *either* the 'assert' or 'child' events until an indented line is
|
328 | encountered. *Any* test point with yaml diagnostics needs to wait to
|
329 | see if it will be followed by a `{` indicating a subtest.
|