You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: readme.md
+91-45Lines changed: 91 additions & 45 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -67,19 +67,18 @@ Install AVA globally `$ npm install --global ava` and run `$ ava --init` (with a
67
67
68
68
```js
69
69
importtestfrom'ava';
70
+
importdelayfrom'delay';
70
71
71
72
test('foo', t=> {
72
73
t.pass();
73
-
t.end();
74
74
});
75
75
76
-
test('bar', t=> {
77
-
t.plan(2);
76
+
constbar=Promise.resolve('bar').then(delay(200));
78
77
79
-
setTimeout(()=> {
80
-
t.is('bar', 'bar');
81
-
t.same(['a', 'b'], ['a', 'b']);
82
-
}, 100);
78
+
test('bar', asynct=> {
79
+
t.plan(2);
80
+
81
+
t.is(await bar, 'bar');
83
82
});
84
83
```
85
84
@@ -121,9 +120,13 @@ Files starting with `_` are ignored. This can be useful for having helpers in th
121
120
122
121
## Documentation
123
122
124
-
Tests 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.
123
+
Tests are run asynchronously and require you to return a supported async object (a promise, or [observable](https://github.com/zenparsing/zen-observable)). We *highly* recommend the use of [async functions](#async-function-support); They make async code concise and readable, and they implicitly return a promise, so you don't need to.
125
124
126
-
You have to define all tests synchronously, meaning you can't define a test in the next tick, e.g. inside a `setTimeout`.
125
+
If you do not return one of the supported async objects mentioned above, the test is considered to be synchronous and ended immediately.
126
+
127
+
If you are unable to use promises or other supported async objects, you may enable legacy async support by defining your test with `test.async([title', fn)`. Tests declared this way **must** be manually ended with `t.end()`.
128
+
129
+
You must define all tests synchronously. They can't be defined inside `setTimeout`, `setImmediate`, etc.
127
130
128
131
Test 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
132
@@ -134,7 +137,6 @@ To create a test, you call the `test` function you `require`d from AVA and pass
134
137
```js
135
138
test('name', t=> {
136
139
t.pass();
137
-
t.end();
138
140
});
139
141
```
140
142
@@ -144,41 +146,86 @@ Naming a test is optional, but you're recommended to use one if you have more th
144
146
145
147
```js
146
148
test(t=> {
147
-
t.end();
149
+
t.pass();
148
150
});
149
151
```
150
152
151
153
You can also choose to use a named function instead:
152
154
153
155
```js
154
156
test(functionname(t) {
155
-
t.end();
157
+
t.pass();
156
158
});
157
159
```
158
160
159
-
### Planned assertions
161
+
### Assertion plan
160
162
161
-
Planned 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.
163
+
An assertion plan can be used to ensure a specific number of assertions are made.
164
+
In the most common scenario, it validates that the test did not exit before executing the expected number of assertions.
165
+
It also fails the test if too many assertions are executed (Useful if you have assertions inside callbacks or loops).
162
166
163
167
This will result in a passed test:
164
168
165
169
```js
166
170
test(t=> {
167
171
t.plan(1);
168
172
173
+
returnPromise.resolve(3).then(n=> {
174
+
t.is(n, 3);
175
+
});
176
+
});
177
+
178
+
test.async(t=> {
169
179
setTimeout(() => {
170
180
t.pass();
181
+
t.end();
171
182
}, 100);
172
183
});
173
184
```
174
185
186
+
#### WARNING: Recent breaking change.
187
+
188
+
AVA no longer supports automatically ending tests via `t.plan(...)`.
189
+
This helps prevent false positives if you add assertions, but forget to increase your plan count.
190
+
191
+
```js
192
+
// This no longer works
193
+
194
+
test('auto ending is dangerous', t=> {
195
+
t.plan(2);
196
+
197
+
t.pass();
198
+
t.pass();
199
+
200
+
// auto-ending after reaching the planned two assertions will miss this final one
201
+
setTimeout(() =>t.fail(), 10000);
202
+
});
203
+
```
204
+
205
+
For this to work, you now must use the legacy `async` test mode, and explicitly call `t.end()`.
206
+
207
+
```js
208
+
test('explicitly end your tests', t=> {
209
+
t.plan(2);
210
+
211
+
t.pass();
212
+
t.pass();
213
+
214
+
setTimeout(() => {
215
+
// This failure is now reliably caught.
216
+
t.fail();
217
+
t.end();
218
+
}, 1000);
219
+
});
220
+
```
221
+
175
222
### Serial-tests
176
223
177
224
While 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
225
179
226
```js
180
227
test.serial(t=> {
181
-
t.end();
228
+
t.pass();
182
229
});
183
230
```
184
231
@@ -189,12 +236,10 @@ Only-tests enforces only those tests to be run. This can be useful for running o
189
236
```js
190
237
test('will not be run', t=> {
191
238
t.fail();
192
-
t.end();
193
239
})
194
240
195
241
test.only('will be run', t=> {
196
242
t.pass();
197
-
t.end();
198
243
});
199
244
```
200
245
@@ -203,8 +248,8 @@ test.only('will be run', t => {
203
248
Skip-tests are shown in the output as skipped but never run.
204
249
205
250
```js
206
-
test.skip('unicorn', t=> {
207
-
t.end();
251
+
test.skip('will not be run', t=> {
252
+
t.fail();
208
253
});
209
254
```
210
255
@@ -217,32 +262,42 @@ used in the same manner as `test()`. The test function given to `test.before()`
217
262
```js
218
263
test.before(t=> {
219
264
// this runs before all tests
220
-
t.end();
221
265
});
222
266
223
267
test.before(t=> {
224
268
// this runs after the above, but before tests
225
-
t.end();
226
269
});
227
270
228
271
test.after('cleanup', t=> {
229
272
// this runs after all tests
230
-
t.end();
231
273
});
232
274
233
275
test.beforeEach(t=> {
234
276
// this runs before each test
235
-
t.end();
236
277
});
237
278
238
279
test.afterEach(t=> {
239
280
// this runs after each test
240
-
t.end();
241
281
});
242
282
243
283
test(t=> {
244
284
// regular test
245
-
t.end();
285
+
});
286
+
```
287
+
288
+
Both modern and legacy async support are available for hooks
289
+
290
+
```js
291
+
test.before(asynct=> {
292
+
awaitpromiseFn();
293
+
});
294
+
295
+
test.async.beforeEach(t=> {
296
+
setTimeout(t.end);
297
+
});
298
+
299
+
test.afterEach.async(t=> {
300
+
setTimeout(t.end);
246
301
});
247
302
```
248
303
@@ -251,12 +306,10 @@ The `beforeEach` & `afterEach` hooks can share context with the test:
251
306
```js
252
307
test.beforeEach(t=> {
253
308
t.context.data=generateUniqueData();
254
-
t.end();
255
309
});
256
310
257
311
test(t=> {
258
312
t.is(t.context.data+'bar', 'foobar');
259
-
t.end();
260
313
});
261
314
```
262
315
@@ -265,12 +318,10 @@ The context is by default an object, but it can also be directly assigned:
265
318
```js
266
319
test.beforeEach(t=> {
267
320
t.context='unicorn';
268
-
t.end();
269
321
});
270
322
271
323
test(t=> {
272
324
t.is(t.context, 'unicorn');
273
-
t.end();
274
325
});
275
326
```
276
327
@@ -296,7 +347,6 @@ import assert from 'assert';
296
347
297
348
test(t=> {
298
349
assert(true);
299
-
t.end();
300
350
});
301
351
```
302
352
@@ -309,7 +359,6 @@ Just write your tests in ES2015. No extra setup needed.
309
359
```js
310
360
test(t=> {
311
361
t.pass();
312
-
t.end();
313
362
});
314
363
```
315
364
@@ -337,7 +386,6 @@ import foo from './foo'; // <-- foo can be written in ES2015!
337
386
338
387
test('foo bar', t=> {
339
388
t.same('baz', foo('bar'));
340
-
t.end();
341
389
});
342
390
```
343
391
@@ -385,31 +433,32 @@ test(async t => {
385
433
});
386
434
```
387
435
388
-
*You don't have to manually call `t.end()`.*
389
-
390
436
### Observable support
391
437
392
438
AVA comes with builtin support for [observables](https://github.com/zenparsing/es-observable).
439
+
If you return an observable from a test, AVA will automatically consume it to completion before ending the test.
440
+
*You don't have to use legacy `test.async` mode or `t.end()`.*
393
441
394
442
```js
395
443
test(t=> {
396
-
returnObservable.of(1, 2, 3).map(n=> {
397
-
t.true(n >0);
398
-
return n * n;
399
-
});
444
+
t.plan(3);
445
+
returnObservable.of(1, 2, 3, 4, 5, 6)
446
+
.filter(n=> {
447
+
// only even numbers
448
+
return n %2===0;
449
+
})
450
+
.map(() =>t.pass());
400
451
});
401
452
```
402
453
403
-
*You don't have to manually call `t.end()`.*
404
-
405
454
### Callback support
406
455
407
456
AVA supports using `t.end` as the final callback when using node-style
408
457
error-first callback APIs. AVA will consider any truthy value passed as
409
-
the first argument to `t.end` to be an error.
458
+
the first argument to `t.end` to be an error. Note that `t.end` requires legacy `test.async` mode.
410
459
411
460
```js
412
-
test(t=> {
461
+
test.async(t=> {
413
462
// t.end automatically checks for error as first argument
414
463
fs.readFile('data.txt', t.end);
415
464
});
@@ -461,7 +510,6 @@ Assertions are mixed into the test [context](#context):
0 commit comments