UNPKG

15.4 kBMarkdownView Raw
1# ![AVA](media/header.png)
2
3> Futuristic test runner
4
5[![Build Status: Linux](https://travis-ci.org/sindresorhus/ava.svg?branch=master)](https://travis-ci.org/sindresorhus/ava) [![Build status: Windows](https://ci.appveyor.com/api/projects/status/igogxrcmhhm085co/branch/master?svg=true)](https://ci.appveyor.com/project/sindresorhus/ava/branch/master) [![Coverage Status](https://coveralls.io/repos/sindresorhus/ava/badge.svg?branch=master&service=github)](https://coveralls.io/github/sindresorhus/ava?branch=master) [![Gitter](https://img.shields.io/badge/Gitter-Join_the_AVA_chat_%E2%86%92-00d06f.svg)](https://gitter.im/sindresorhus/ava)
6
7Even though JavaScript is single-threaded, IO in Node.js can happen in parallel due to its async nature. AVA takes advantage of this and runs your tests concurrently, which is especially beneficial for IO heavy tests. In addition, test files are run in parallel as separate processes, giving you even better performance and an isolated environment for each test file. [Switching](https://github.com/sindresorhus/pageres/commit/663be15acb3dd2eb0f71b1956ef28c2cd3fdeed0) from Mocha to AVA in Pageres brought the test time down from 31 sec to 11 sec. Having tests run concurrently forces you to write atomic tests, meaning tests don't depend on global state or the state of other tests, which is a great thing!
8
9
10## Table of Contents
11
12- [Usage](#usage)
13- [CLI Usage](#cli)
14- [Documentation](#documentation)
15- [API](#api)
16- [Assertions](#assertions)
17- [FAQ](#faq)
18
19
20## Why AVA?
21
22- Minimal and fast
23- Simple test syntax
24- Runs tests concurrently
25- Enforces writing atomic tests
26- No implicit globals
27- [Isolated environment for each test file](#isolated-environment)
28- [Write your tests in ES2015](#es2015-support)
29- [Promise support](#promise-support)
30- [Generator function support](#generator-function-support)
31- [Async function support](#async-function-support)
32- [Observable support](#observable-support)
33- [Enhanced asserts](#enhanced-asserts)
34
35
36## Test syntax
37
38```js
39import test from 'ava';
40
41test(t => {
42 t.same([1, 2], [1, 2]);
43 t.end();
44});
45```
46
47
48## Usage
49
50#### Initialize
51
52Install AVA globally `$ npm install --global ava` and run `$ ava --init` (with any options) to add AVA to your package.json or create one.
53
54```json
55{
56 "name": "awesome-package",
57 "scripts": {
58 "test": "ava"
59 },
60 "devDependencies": {
61 "ava": "^0.3.0"
62 }
63}
64```
65
66#### Create your test file
67
68```js
69import test from 'ava';
70
71test('foo', t => {
72 t.pass();
73 t.end();
74});
75
76test('bar', t => {
77 t.plan(2);
78
79 setTimeout(() => {
80 t.is('bar', 'bar');
81 t.same(['a', 'b'], ['a', 'b']);
82 }, 100);
83});
84```
85
86<img src="screenshot.png" width="150" align="right">
87
88#### Run it
89
90```
91$ npm test
92```
93
94
95## CLI
96
97```
98$ ava --help
99
100 Usage
101 ava [<file|folder|glob> ...]
102
103 Options
104 --init Add AVA to your project
105 --fail-fast Stop after first test failure
106 --serial Run tests serially
107
108 Examples
109 ava
110 ava test.js test2.js
111 ava test-*.js
112 ava --init
113 ava --init foo.js
114
115 Default patterns when no arguments:
116 test.js test-*.js test/*.js
117```
118
119Files starting with `_` are ignored. This can be useful for having helpers in the same directory as your test files.
120
121
122## Documentation
123
124Tests are run asynchronously and require you to either set planned assertions `t.plan(1)`, explicitly end the test when done `t.end()`, or return a promise. [Async functions](#async-function-support) already returns a promise implicitly, so no need for you to explicitly return a promise in that case.
125
126You have to define all tests synchronously, meaning you can't define a test in the next tick, e.g. inside a `setTimeout`.
127
128Test files are run from their current directory, so [`process.cwd()`](https://nodejs.org/api/process.html#process_process_cwd) is always the same as [`__dirname`](https://nodejs.org/api/globals.html#globals_dirname). You can just use relative paths instead of doing `path.join(__dirname, 'relative/path')`.
129
130### Test anatomy
131
132To create a test, you call the `test` function you `require`d from AVA and pass in an optional test name and a function containing the test execution. The passed function is given the context as the first argument, where you can call the different AVA methods and [assertions](#assertions).
133
134```js
135test('name', t => {
136 t.pass();
137 t.end();
138});
139```
140
141### Optional test name
142
143Naming a test is optional, but you're recommended to use one if you have more than one test.
144
145```js
146test(t => {
147 t.end();
148});
149```
150
151You can also choose to use a named function instead:
152
153```js
154test(function name(t) {
155 t.end();
156});
157```
158
159### Planned assertions
160
161Planned assertions are useful for being able to assert that all async actions happened. It also comes with the benefit of not having to manually end the test.
162
163This will result in a passed test:
164
165```js
166test(t => {
167 t.plan(1);
168
169 setTimeout(() => {
170 t.pass();
171 }, 100);
172});
173```
174
175### Serial test execution
176
177While concurrency is awesome, there are some things that can't be done concurrently. In these rare cases, you can call `test.serial`, which will force those tests to run serially before the concurrent ones.
178
179```js
180test.serial(t => {
181 t.end();
182});
183```
184
185### Skipped tests
186
187Skipped tests are shown in the output as skipped but never run.
188
189```js
190test.skip('unicorn', t => {
191 t.end();
192});
193```
194
195### Before & after hooks
196
197When setup and/or teardown is required, you can use `test.before()` and `test.after()`,
198used in the same manner as `test()`. The test function given to `test.before()` and `test.after()` is called before/after all tests. You can also use `test.beforeEach()` and `test.afterEach()` if you need setup/teardown for each test. Hooks are run serially in the test file. Add as many of these as you want. You can optionally specify a title that is shown on failure.
199
200
201```js
202test.before(t => {
203 // this runs before all tests
204 t.end();
205});
206
207test.before(t => {
208 // this runs after the above, but before tests
209 t.end();
210});
211
212test.after('cleanup', t => {
213 // this runs after all tests
214 t.end();
215});
216
217test.beforeEach(t => {
218 // this runs before each test
219 t.end();
220});
221
222test.afterEach(t => {
223 // this runs after each test
224 t.end();
225});
226
227test(t => {
228 // regular test
229 t.end();
230});
231```
232
233The `beforeEach` & `afterEach` hooks can share context with the test:
234
235```js
236test.beforeEach(t => {
237 t.context.data = generateUniqueData();
238 t.end();
239});
240
241test(t => {
242 t.is(t.context.data + 'bar', 'foobar');
243 t.end();
244});
245```
246
247The context is by default an object, but it can also be directly assigned:
248
249```js
250test.beforeEach(t => {
251 t.context = 'unicorn';
252 t.end();
253});
254
255test(t => {
256 t.is(t.context, 'unicorn');
257 t.end();
258});
259```
260
261### Custom assertion module
262
263You can use any assertion module instead or in addition to the one that comes with AVA, but you won't be able to use the `.plan()` method, [yet](https://github.com/sindresorhus/ava/issues/25).
264
265```js
266import assert from 'assert';
267
268test(t => {
269 assert(true);
270 t.end();
271});
272```
273
274### ES2015 support
275
276AVA comes with builtin support for ES2015 through [Babel](https://babeljs.io).
277
278Just write your tests in ES2015. No extra setup needed.
279
280```js
281test(t => {
282 t.pass();
283 t.end();
284});
285```
286
287You can also use your own local Babel version:
288
289```json
290{
291 "devDependencies": {
292 "ava": "^0.3.0",
293 "babel-core": "^5.8.0"
294 }
295}
296```
297
298### Promise support
299
300If you return a promise in the test you don't need to explicitly end the test as it will end when the promise resolves.
301
302```js
303test(t => {
304 return somePromise().then(result => {
305 t.is(result, 'unicorn');
306 });
307});
308```
309
310### Generator function support
311
312AVA comes with builtin support for [generator functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*).
313
314```js
315test(function * (t) {
316 const value = yield generatorFn();
317 t.true(value);
318});
319```
320
321*You don't have to manually call `t.end()`.*
322
323### Async function support
324
325AVA comes with builtin support for [async functions](https://tc39.github.io/ecmascript-asyncawait/) *(async/await)*.
326
327```js
328test(async function (t) {
329 const value = await promiseFn();
330 t.true(value);
331});
332
333// async arrow function
334test(async t => {
335 const value = await promiseFn();
336 t.true(value);
337});
338```
339
340*You don't have to manually call `t.end()`.*
341
342### Observable support
343
344AVA comes with builtin support for [observables](https://github.com/zenparsing/es-observable).
345
346```js
347test(t => {
348 return Observable.of(1, 2, 3).map(n => {
349 t.true(n > 0);
350 return n * n;
351 });
352});
353```
354
355*You don't have to manually call `t.end()`.*
356
357### Callback support
358
359AVA supports using `t.end` as the final callback when using node-style
360error-first callback APIs. AVA will consider any truthy value passed as
361the first argument to `t.end` to be an error.
362
363```js
364test(t => {
365 // t.end automatically checks for error as first argument
366 fs.readFile('data.txt', t.end);
367});
368```
369
370
371## API
372
373### test([title], body)
374### test.serial([title], body)
375### test.skip([title], body)
376### test.before([title], body)
377### test.after([title], body)
378### test.beforeEach([title], body)
379### test.afterEach([title], body)
380
381#### title
382
383Type: `string`
384
385Test title.
386
387#### body(context)
388
389Type: `function`
390
391Should contain the actual test.
392
393##### context
394
395Passed into the test function and contains the different AVA methods and [assertions](#assertions).
396
397###### .plan(count)
398
399Plan how many assertion there are in the test. The test will fail if the actual assertion count doesn't match planned assertions. When planned assertions are used you don't need to explicitly end the test.
400
401Be aware that this doesn't work with custom assert modules. You must then call `.end()` explicitly.
402
403###### .end()
404
405End the test. Use this when `plan()` is not used.
406
407
408## Assertions
409
410Assertions are mixed into the test [context](#context):
411
412```js
413test(t => {
414 t.ok('unicorn'); // assertion
415 t.end();
416});
417```
418
419### .pass([message])
420
421Passing assertion.
422
423### .fail([message])
424
425Failing assertion.
426
427### .ok(value, [message])
428
429Assert that `value` is truthy.
430
431### .notOk(value, [message])
432
433Assert that `value` is falsy.
434
435### .true(value, [message])
436
437Assert that `value` is `true`.
438
439### .false(value, [message])
440
441Assert that `value` is `false`.
442
443### .is(value, expected, [message])
444
445Assert that `value` is equal to `expected`.
446
447### .not(value, expected, [message])
448
449Assert that `value` is not equal to `expected`.
450
451### .same(value, expected, [message])
452
453Assert that `value` is deep equal to `expected`.
454
455### .notSame(value, expected, [message])
456
457Assert that `value` is not deep equal to `expected`.
458
459### .throws(function|promise, error, [message])
460
461Assert that `function` throws an error or `promise` rejects.
462
463`error` can be a constructor, regex, error message or validation function.
464
465### .doesNotThrow(function|promise, [message])
466
467Assert that `function` doesn't throw an `error` or `promise` resolves.
468
469### .regexTest(regex, contents, [message])
470
471Assert that `regex` matches `contents`.
472
473### .ifError(error, [message])
474
475Assert that `error` is falsy.
476
477
478## Enhanced asserts
479
480AVA comes with [`power-assert`](https://github.com/power-assert-js/power-assert) builtin, giving you more descriptive assertion messages. It reads your test and tries to infer more information from the code.
481
482The following test:
483
484```js
485test(t => {
486 const x = 'foo';
487 t.ok(x === 'bar');
488 t.end();
489});
490```
491
492Would normally give the unhelpful output:
493
494```
495false === true
496```
497
498With the enhanced asserts, you'll get:
499
500```
501t.ok(x === 'bar')
502 |
503 "foo"
504```
505
506True, you could use `t.is()` in this case, and probably should, but this is just a simple example.
507
508Let try a more advanced example:
509
510```js
511test(t => {
512 const a = /foo/;
513 const b = 'bar';
514 const c = 'baz';
515 t.ok(a.test(b) || b === c);
516 t.end();
517});
518```
519
520And there you go:
521
522```
523t.ok(a.test(b) || b === c)
524 | | | |
525 | "bar" "bar" "baz"
526 false
527```
528
529All the assert methods are enhanced.
530
531Have fun!
532
533
534## Isolated environment
535
536Each test file is run in a separate Node.js process. This comes with a lot of benefits. Different test files can no longer affect each other. Like test files mocking with the global environment, overriding builtins, etc. However, it's mainly done for performance reasons. Even though Node.js can run async IO concurrently, that doesn't help much when tests are heavy on synchronous operations, which blocks the main thread. By running tests concurrently and test files in parallel we take full advantage of modern systems.
537
538
539## Tips
540
541### Temp files
542
543Running tests concurrently comes with some challenges, doing IO is one. Usually, serial tests just create temp directories in the current test directory and cleans it up at the end. This won't work when you run tests concurrently as tests will conflict with each other. The correct way to do it is to use a new temp directory for each test. The [`tempfile`](https://github.com/sindresorhus/tempfile) and [`temp-write`](https://github.com/sindresorhus/temp-write) modules can be helpful.
544
545### Debugging
546
547AVA runs tests concurrently by default, which is suboptimal when you need to debug something. Instead, run tests serially with the `--serial` option:
548
549```
550$ ava --serial
551```
552
553### Code coverage
554
555You can't use [`istanbul`](https://github.com/gotwarlost/istanbul) for code coverage as AVA [spawns the test files](#isolated-environment), but you can use [`nyc`](https://github.com/bcoe/nyc) instead, which is basically `istanbul` with support for subprocesses.
556
557
558## FAQ
559
560### Why not `mocha`, `tape`, `node-tap`?
561
562Mocha requires you to use implicit globals like `describe` and `it` with the default interface (which most people use), too unopinionated, bloated, synchronous by default, serial test execution, and slow. Tape and node-tap are pretty good. AVA is highly inspired by their syntax. However, they both execute tests serially and they've made [TAP](https://testanything.org) a first-class citizen which has IMHO made their codebases a bit convoluted and coupled. TAP output is hard to read so you always end up using an external tap reporter. AVA is highly opinionated and concurrent. It comes with a default simple reporter and will in the future support TAP through a reporter.
563
564### How is the name written and pronounced?
565
566AVA, not Ava or ava. Pronounced [`/ˈeɪvə/` ay-və](media/pronunciation.m4a?raw=true).
567
568### What is the header background?
569
570[Andromeda galaxy.](https://simple.wikipedia.org/wiki/Andromeda_galaxy)
571
572### Concurrency vs. parallelism
573
574Concurrency is not parallelism. It enables parallelism. [Learn more.](http://stackoverflow.com/q/1050222)
575
576
577## Support
578
579- [Stack Overflow](https://stackoverflow.com/questions/tagged/ava)
580- [Gitter chat](https://gitter.im/sindresorhus/ava)
581
582
583## Related
584
585- [gulp-ava](https://github.com/sindresorhus/gulp-ava) - Run tests with gulp
586- [grunt-ava](https://github.com/sindresorhus/grunt-ava) - Run tests with grunt
587
588
589## Created by
590
591[![Sindre Sorhus](https://avatars.githubusercontent.com/u/170270?s=130)](http://sindresorhus.com) | [![Kevin Mårtensson](https://avatars.githubusercontent.com/u/709159?s=130)](https://github.com/kevva) | [![Vadim Demedes](https://avatars.githubusercontent.com/u/697676?s=130)](https://github.com/vdemedes)
592---|---|---
593[Sindre Sorhus](http://sindresorhus.com) | [Kevin Mårtensson](https://github.com/kevva) | [Vadim Demedes](https://github.com/vdemedes)
594
595
596<div align="center">
597 <br>
598 <br>
599 <br>
600 <img src="https://cdn.rawgit.com/sindresorhus/ava/fe1cea1ca3d2c8518c0cc39ec8be592beab90558/media/logo.svg" width="200" alt="AVA">
601 <br>
602 <br>
603</div>
604