UNPKG

12.1 kBMarkdownView Raw
1# tape
2
3tap-producing test harness for node and browsers
4
5[![browser support](https://ci.testling.com/substack/tape.png)](http://ci.testling.com/substack/tape)
6
7[![build status](https://secure.travis-ci.org/substack/tape.svg?branch=master)](http://travis-ci.org/substack/tape)
8
9![tape](http://substack.net/images/tape_drive.png)
10
11# example
12
13``` js
14var test = require('tape');
15
16test('timing test', function (t) {
17 t.plan(2);
18
19 t.equal(typeof Date.now, 'function');
20 var start = Date.now();
21
22 setTimeout(function () {
23 t.equal(Date.now() - start, 100);
24 }, 100);
25});
26```
27
28```
29$ node example/timing.js
30TAP version 13
31# timing test
32ok 1 should be equal
33not ok 2 should be equal
34 ---
35 operator: equal
36 expected: 100
37 actual: 107
38 ...
39
401..2
41# tests 2
42# pass 1
43# fail 1
44```
45
46# usage
47
48You always need to `require('tape')` in test files. You can run the tests by
49usual node means (`require('test-file.js')` or `node test-file.js`). You can
50also run tests using the `tape` binary to utilize globbing, on Windows for
51example:
52
53```sh
54$ tape tests/**/*.js
55```
56
57`tape`'s arguments are passed to the
58[`glob`](https://www.npmjs.com/package/glob) module. If you want `glob` to
59perform the expansion on a system where the shell performs such expansion, quote
60the arguments as necessary:
61
62```sh
63$ tape 'tests/**/*.js'
64$ tape "tests/**/*.js"
65```
66
67## Preloading modules
68
69Additionally, it is possible to make `tape` load one or more modules before running any tests, by using the `-r` or `--require` flag. Here's an example that loads [babel-register](http://babeljs.io/docs/usage/require/) before running any tests, to allow for JIT compilation:
70
71```sh
72$ tape -r babel-register tests/**/*.js
73```
74
75Depending on the module you're loading, you may be able to paramaterize it using environment variables or auxiliary files. Babel, for instance, will load options from [`.babelrc`](http://babeljs.io/docs/usage/babelrc/) at runtime.
76
77The `-r` flag behaves exactly like node's `require`, and uses the same module resolution algorithm. This means that if you need to load local modules, you have to prepend their path with `./` or `../` accordingly.
78
79For example:
80
81```sh
82$ tape -r ./my/local/module tests/**/*.js
83```
84
85Please note that all modules loaded using the `-r` flag will run *before* any tests, regardless of when they are specified. For example, `tape -r a b -r c` will actually load `a` and `c` *before* loading `b`, since they are flagged as required modules.
86
87# things that go well with tape
88
89tape maintains a fairly minimal core. Additional features are usually added by using another module alongside tape.
90
91## pretty reporters
92
93The default TAP output is good for machines and humans that are robots.
94
95If you want a more colorful / pretty output there are lots of modules on npm
96that will output something pretty if you pipe TAP into them:
97
98 - https://github.com/scottcorgan/tap-spec
99 - https://github.com/scottcorgan/tap-dot
100 - https://github.com/substack/faucet
101 - https://github.com/juliangruber/tap-bail
102 - https://github.com/kirbysayshi/tap-browser-color
103 - https://github.com/gummesson/tap-json
104 - https://github.com/derhuerst/tap-min
105 - https://github.com/calvinmetcalf/tap-nyan
106 - https://www.npmjs.org/package/tap-pessimist
107 - https://github.com/toolness/tap-prettify
108 - https://github.com/shuhei/colortape
109 - https://github.com/aghassemi/tap-xunit
110 - https://github.com/namuol/tap-difflet
111 - https://github.com/gritzko/tape-dom
112 - https://github.com/axross/tap-diff
113 - https://github.com/axross/tap-notify
114 - https://github.com/zoubin/tap-summary
115 - https://github.com/Hypercubed/tap-markdown
116
117To use them, try `node test/index.js | tap-spec` or pipe it into one
118of the modules of your choice!
119
120## uncaught exceptions
121
122By default, uncaught exceptions in your tests will not be intercepted, and will cause tape to crash. If you find this behavior undesirable, use [tape-catch](https://github.com/michaelrhodes/tape-catch) to report any exceptions as TAP errors.
123
124## other
125
126- CoffeeScript support with https://www.npmjs.com/package/coffeetape
127- Promise support with https://www.npmjs.com/package/blue-tape
128- ES6 support with https://www.npmjs.com/package/babel-tape-runner
129
130# methods
131
132The assertion methods in tape are heavily influenced or copied from the methods
133in [node-tap](https://github.com/isaacs/node-tap).
134
135```
136var test = require('tape')
137```
138
139## test([name], [opts], cb)
140
141Create a new test with an optional `name` string and optional `opts` object.
142`cb(t)` fires with the new test object `t` once all preceeding tests have
143finished. Tests execute serially.
144
145Available `opts` options are:
146- opts.skip = true/false. See test.skip.
147- opts.timeout = 500. Set a timeout for the test, after which it will fail.
148 See test.timeoutAfter.
149- opts.objectPrintDepth = 5. Configure max depth of expected / actual object
150 printing.
151
152If you forget to `t.plan()` out how many assertions you are going to run and you
153don't call `t.end()` explicitly, your test will hang.
154
155## test.skip(name, cb)
156
157Generate a new test that will be skipped over.
158
159## test.onFinish(fn)
160
161The onFinish hook will get invoked when ALL tape tests have finished
162right before tape is about to print the test summary.
163
164## t.plan(n)
165
166Declare that `n` assertions should be run. `t.end()` will be called
167automatically after the `n`th assertion. If there are any more assertions after
168the `n`th, or after `t.end()` is called, they will generate errors.
169
170## t.end(err)
171
172Declare the end of a test explicitly. If `err` is passed in `t.end` will assert
173that it is falsey.
174
175## t.fail(msg)
176
177Generate a failing assertion with a message `msg`.
178
179## t.pass(msg)
180
181Generate a passing assertion with a message `msg`.
182
183## t.timeoutAfter(ms)
184
185Automatically timeout the test after X ms.
186
187## t.skip(msg)
188
189Generate an assertion that will be skipped over.
190
191## t.ok(value, msg)
192
193Assert that `value` is truthy with an optional description of the assertion `msg`.
194
195Aliases: `t.true()`, `t.assert()`
196
197## t.notOk(value, msg)
198
199Assert that `value` is falsy with an optional description of the assertion `msg`.
200
201Aliases: `t.false()`, `t.notok()`
202
203## t.error(err, msg)
204
205Assert that `err` is falsy. If `err` is non-falsy, use its `err.message` as the
206description message.
207
208Aliases: `t.ifError()`, `t.ifErr()`, `t.iferror()`
209
210## t.equal(actual, expected, msg)
211
212Assert that `actual === expected` with an optional description of the assertion `msg`.
213
214Aliases: `t.equals()`, `t.isEqual()`, `t.is()`, `t.strictEqual()`,
215`t.strictEquals()`
216
217## t.notEqual(actual, expected, msg)
218
219Assert that `actual !== expected` with an optional description of the assertion `msg`.
220
221Aliases: `t.notEquals()`, `t.notStrictEqual()`, `t.notStrictEquals()`,
222`t.isNotEqual()`, `t.isNot()`, `t.not()`, `t.doesNotEqual()`, `t.isInequal()`
223
224## t.deepEqual(actual, expected, msg)
225
226Assert that `actual` and `expected` have the same structure and nested values using
227[node's deepEqual() algorithm](https://github.com/substack/node-deep-equal)
228with strict comparisons (`===`) on leaf nodes and an optional description of the assertion `msg`.
229
230Aliases: `t.deepEquals()`, `t.isEquivalent()`, `t.same()`
231
232## t.notDeepEqual(actual, expected, msg)
233
234Assert that `actual` and `expected` do not have the same structure and nested values using
235[node's deepEqual() algorithm](https://github.com/substack/node-deep-equal)
236with strict comparisons (`===`) on leaf nodes and an optional description of the assertion `msg`.
237
238Aliases: `t.notEquivalent()`, `t.notDeeply()`, `t.notSame()`,
239`t.isNotDeepEqual()`, `t.isNotDeeply()`, `t.isNotEquivalent()`,
240`t.isInequivalent()`
241
242## t.deepLooseEqual(actual, expected, msg)
243
244Assert that `actual` and `expected` have the same structure and nested values using
245[node's deepEqual() algorithm](https://github.com/substack/node-deep-equal)
246with loose comparisons (`==`) on leaf nodes and an optional description of the assertion `msg`.
247
248Aliases: `t.looseEqual()`, `t.looseEquals()`
249
250## t.notDeepLooseEqual(actual, expected, msg)
251
252Assert that `actual` and `expected` do not have the same structure and nested values using
253[node's deepEqual() algorithm](https://github.com/substack/node-deep-equal)
254with loose comparisons (`==`) on leaf nodes and an optional description of the assertion `msg`.
255
256Aliases: `t.notLooseEqual()`, `t.notLooseEquals()`
257
258## t.throws(fn, expected, msg)
259
260Assert that the function call `fn()` throws an exception. `expected`, if present, must be a `RegExp` or `Function`. The `RegExp` matches the string representation of the exception, as generated by `err.toString()`. The `Function` is the exception thrown (e.g. `Error`). `msg` is an optional description of the assertion.
261
262## t.doesNotThrow(fn, expected, msg)
263
264Assert that the function call `fn()` does not throw an exception. `msg` is an optional description of the assertion.
265
266## t.test(name, [opts], cb)
267
268Create a subtest with a new test handle `st` from `cb(st)` inside the current
269test `t`. `cb(st)` will only fire when `t` finishes. Additional tests queued up
270after `t` will not be run until all subtests finish.
271
272You may pass the same options that [`test()`](#testname-opts-cb) accepts.
273
274## t.comment(message)
275
276Print a message without breaking the tap output. (Useful when using e.g. `tap-colorize` where output is buffered & `console.log` will print in incorrect order vis-a-vis tap output.)
277
278## var htest = test.createHarness()
279
280Create a new test harness instance, which is a function like `test()`, but with
281a new pending stack and test state.
282
283By default the TAP output goes to `console.log()`. You can pipe the output to
284someplace else if you `htest.createStream().pipe()` to a destination stream on
285the first tick.
286
287## test.only(name, cb)
288
289Like `test(name, cb)` except if you use `.only` this is the only test case
290that will run for the entire process, all other test cases using tape will
291be ignored
292
293## var stream = test.createStream(opts)
294
295Create a stream of output, bypassing the default output stream that writes
296messages to `console.log()`. By default `stream` will be a text stream of TAP
297output, but you can get an object stream instead by setting `opts.objectMode` to
298`true`.
299
300### tap stream reporter
301
302You can create your own custom test reporter using this `createStream()` api:
303
304``` js
305var test = require('tape');
306var path = require('path');
307
308test.createStream().pipe(process.stdout);
309
310process.argv.slice(2).forEach(function (file) {
311 require(path.resolve(file));
312});
313```
314
315You could substitute `process.stdout` for whatever other output stream you want,
316like a network connection or a file.
317
318Pass in test files to run as arguments:
319
320```
321$ node tap.js test/x.js test/y.js
322TAP version 13
323# (anonymous)
324not ok 1 should be equal
325 ---
326 operator: equal
327 expected: "boop"
328 actual: "beep"
329 ...
330# (anonymous)
331ok 2 should be equal
332ok 3 (unnamed assert)
333# wheee
334ok 4 (unnamed assert)
335
3361..4
337# tests 4
338# pass 3
339# fail 1
340```
341
342### object stream reporter
343
344Here's how you can render an object stream instead of TAP:
345
346``` js
347var test = require('tape');
348var path = require('path');
349
350test.createStream({ objectMode: true }).on('data', function (row) {
351 console.log(JSON.stringify(row))
352});
353
354process.argv.slice(2).forEach(function (file) {
355 require(path.resolve(file));
356});
357```
358
359The output for this runner is:
360
361```
362$ node object.js test/x.js test/y.js
363{"type":"test","name":"(anonymous)","id":0}
364{"id":0,"ok":false,"name":"should be equal","operator":"equal","actual":"beep","expected":"boop","error":{},"test":0,"type":"assert"}
365{"type":"end","test":0}
366{"type":"test","name":"(anonymous)","id":1}
367{"id":0,"ok":true,"name":"should be equal","operator":"equal","actual":2,"expected":2,"test":1,"type":"assert"}
368{"id":1,"ok":true,"name":"(unnamed assert)","operator":"ok","actual":true,"expected":true,"test":1,"type":"assert"}
369{"type":"end","test":1}
370{"type":"test","name":"wheee","id":2}
371{"id":0,"ok":true,"name":"(unnamed assert)","operator":"ok","actual":true,"expected":true,"test":2,"type":"assert"}
372{"type":"end","test":2}
373```
374
375# install
376
377With [npm](https://npmjs.org) do:
378
379```
380npm install tape --save-dev
381```
382
383# license
384
385MIT