Skip to content

Commit f72fab4

Browse files
bunysaenovemberborn
andauthoredJun 28, 2020
Don't update snapshots when executing a subset of tests
Co-authored-by: Mark Wubben <mark@novemberborn.net>
1 parent 78cfaa1 commit f72fab4

17 files changed

+221
-7
lines changed
 

‎docs/01-writing-tests.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ You can use the `.only` modifier with all tests. It cannot be used with hooks or
118118

119119
*Note:* The `.only` modifier applies to the test file it's defined in, so if you run multiple test files, tests in other files will still run. If you want to only run the `test.only` test, provide just that test file to AVA.
120120

121+
You cannot update snapshots when using `.only()`.
122+
121123
## Skipping tests
122124

123-
Sometimes failing tests can be hard to fix. You can tell AVA to skip these tests using the `.skip` modifier. They'll still be shown in the output (as having been skipped) but are never run.
125+
Sometimes failing tests can be hard to fix. You can tell AVA to temporarily skip these tests using the `.skip` modifier. They'll still be shown in the output (as having been skipped) but are never run.
124126

125127
```js
126128
test.skip('will not be run', t => {
@@ -130,6 +132,8 @@ test.skip('will not be run', t => {
130132

131133
You must specify the implementation function. You can use the `.skip` modifier with all tests and hooks, but not with `.todo()`. You can not apply further modifiers to `.skip`.
132134

135+
You cannot update snapshots when using `.skip()`. If the test is likely to be failing for a while, use `.failing()` instead.
136+
133137
## Test placeholders ("todo")
134138

135139
You can use the `.todo` modifier when you're planning to write a test. Like skipped tests these placeholders are shown in the output. They only require a title; you cannot specify the implementation function.

‎lib/cli.js

+7
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ exports.run = async () => { // eslint-disable-line complexity
182182
const chalkOptions = {level: combined.color === false ? 0 : require('chalk').level};
183183
const chalk = require('./chalk').set(chalkOptions);
184184

185+
if (combined.updateSnapshots && combined.match) {
186+
exit('Snapshots cannot be updated when matching specific tests.');
187+
}
188+
185189
if (confError) {
186190
if (confError.parent) {
187191
exit(`${confError.message}\n\n${chalk.gray((confError.parent && confError.parent.stack) || confError.parent)}`);
@@ -356,6 +360,9 @@ exports.run = async () => { // eslint-disable-line complexity
356360
pattern: normalizePattern(path.relative(projectDir, path.resolve(process.cwd(), pattern))),
357361
...rest
358362
}));
363+
if (combined.updateSnapshots && filter.some(condition => condition.lineNumbers !== null)) {
364+
exit('Snapshots cannot be updated when selecting specific tests by their line number.');
365+
}
359366

360367
const api = new Api({
361368
cacheEnabled: combined.cache !== false,

‎lib/reporters/default.js

+15
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class Reporter {
153153
this.lineNumberErrors = [];
154154
this.uncaughtExceptions = [];
155155
this.unhandledRejections = [];
156+
this.unsavedSnapshots = [];
156157

157158
this.previousFailures = 0;
158159

@@ -295,6 +296,10 @@ class Reporter {
295296
break;
296297
}
297298

299+
case 'snapshot-error':
300+
this.unsavedSnapshots.push(event);
301+
break;
302+
298303
case 'uncaught-exception': {
299304
this.uncaughtExceptions.push(event);
300305

@@ -749,6 +754,16 @@ class Reporter {
749754
}
750755
}
751756

757+
if (this.unsavedSnapshots.length > 0) {
758+
this.lineWriter.writeLine(colors.title('Could not update snapshots for the following test files:'));
759+
this.lineWriter.writeLine();
760+
for (const event of this.unsavedSnapshots) {
761+
this.lineWriter.writeLine(`${figures.warning} ${this.relativeFile(event.testFile)}`);
762+
}
763+
764+
this.lineWriter.writeLine();
765+
}
766+
752767
if (this.failFastEnabled && (this.stats.remainingTests > 0 || this.stats.files > this.stats.finishedWorkers)) {
753768
let remaining = '';
754769
if (this.stats.remainingTests > 0) {

‎lib/reporters/tap.js

+3
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ class TapReporter {
158158
this.writeTest(evt, {passed: false, todo: true, skip: false});
159159
}
160160

161+
break;
162+
case 'snapshot-error':
163+
this.writeComment(evt, {title: 'Could not update snapshots'});
161164
break;
162165
case 'stats':
163166
this.stats = evt.stats;

‎lib/runner.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Runner extends Emittery {
2323
this.recordNewSnapshots = options.recordNewSnapshots === true;
2424
this.runOnlyExclusive = options.runOnlyExclusive === true;
2525
this.serial = options.serial === true;
26+
this.skippingTests = false;
2627
this.snapshotDir = options.snapshotDir;
2728
this.updateSnapshots = options.updateSnapshots;
2829

@@ -147,6 +148,10 @@ class Runner extends Emittery {
147148
task.metadata.exclusive = matcher([title], this.match).length === 1;
148149
}
149150

151+
if (task.metadata.skipped) {
152+
this.skippingTests = true;
153+
}
154+
150155
if (task.metadata.exclusive) {
151156
this.runOnlyExclusive = true;
152157
}
@@ -182,7 +187,7 @@ class Runner extends Emittery {
182187
fixedLocation: this.snapshotDir,
183188
projectDir: this.projectDir,
184189
recordNewSnapshots: this.recordNewSnapshots,
185-
updating: this.updateSnapshots
190+
updating: this.updateSnapshots && !this.runOnlyExclusive && !this.skippingTests
186191
});
187192
this.emit('dependency', this.snapshots.snapPath);
188193
}
@@ -191,8 +196,12 @@ class Runner extends Emittery {
191196
}
192197

193198
saveSnapshotState() {
199+
if (this.updateSnapshots && (this.runOnlyExclusive || this.skippingTests)) {
200+
return {cannotSave: true};
201+
}
202+
194203
if (this.snapshots) {
195-
return this.snapshots.save();
204+
return {touchedFiles: this.snapshots.save()};
196205
}
197206

198207
if (this.updateSnapshots) {
@@ -201,7 +210,7 @@ class Runner extends Emittery {
201210
// were skipped. Perhaps emit a warning if this occurs?
202211
}
203212

204-
return null;
213+
return {};
205214
}
206215

207216
onRun(runnable) {

‎lib/worker/subprocess.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ ipc.options.then(async options => {
9191

9292
runner.on('finish', () => {
9393
try {
94-
const touchedFiles = runner.saveSnapshotState();
95-
if (touchedFiles) {
94+
const {cannotSave, touchedFiles} = runner.saveSnapshotState();
95+
if (cannotSave) {
96+
ipc.send({type: 'snapshot-error'});
97+
} else if (touchedFiles) {
9698
ipc.send({type: 'touched-files', files: touchedFiles});
9799
}
98100
} catch (error) {

‎test/helpers/exec.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const execa = require('execa');
77
const cliPath = path.resolve(__dirname, '../../cli.js');
88
const serialization = process.versions.node >= '12.16.0' ? 'advanced' : 'json';
99

10+
const normalizePath = (root, file) => path.posix.normalize(path.relative(root, file));
11+
1012
exports.fixture = async (...args) => {
1113
const cwd = path.join(path.dirname(test.meta.file), 'fixtures');
1214
const running = execa.node(cliPath, args, {
@@ -18,6 +20,9 @@ exports.fixture = async (...args) => {
1820
});
1921

2022
const stats = {
23+
failed: [],
24+
skipped: [],
25+
unsavedSnapshots: [],
2126
passed: []
2227
};
2328

@@ -27,9 +32,30 @@ exports.fixture = async (...args) => {
2732
}
2833

2934
switch (message.type) {
35+
case 'selected-test': {
36+
if (message.skip) {
37+
const {title, testFile} = message;
38+
stats.skipped.push({title, file: normalizePath(cwd, testFile)});
39+
}
40+
41+
break;
42+
}
43+
44+
case 'snapshot-error': {
45+
const {testFile} = message;
46+
stats.unsavedSnapshots.push({file: normalizePath(cwd, testFile)});
47+
break;
48+
}
49+
3050
case 'test-passed': {
3151
const {title, testFile} = message;
32-
stats.passed.push({title, file: path.posix.relative(cwd, testFile)});
52+
stats.passed.push({title, file: normalizePath(cwd, testFile)});
53+
break;
54+
}
55+
56+
case 'test-failed': {
57+
const {title, testFile} = message;
58+
stats.failed.push({title, file: normalizePath(cwd, testFile)});
3359
break;
3460
}
3561

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const test = require('ava');
2+
3+
test('always failing snapshot', t => {
4+
t.snapshot(Date.now());
5+
});
6+
7+
test.only('exclusive test', t => { // eslint-disable-line ava/no-only-test
8+
t.pass();
9+
});
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Snapshot report for `contains-only.js`
2+
3+
The actual snapshot is saved in `contains-only.js.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## always failing snapshot
8+
9+
> Snapshot 1
10+
11+
1592749428423
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const test = require('ava');
2+
3+
test('always failing snapshot', t => {
4+
t.snapshot(Date.now());
5+
});
6+
7+
test.skip('skipped test', t => { // eslint-disable-line ava/no-skip-test
8+
t.pass();
9+
});
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Snapshot report for `contains-skip.js`
2+
3+
The actual snapshot is saved in `contains-skip.js.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## always failing snapshot
8+
9+
> Snapshot 1
10+
11+
1592749428431
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"ava": {
3+
"files": [
4+
"*.js"
5+
]
6+
},
7+
"dependencies": {
8+
"ava": "file:../../.."
9+
}
10+
}
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Snapshot report for `test/snapshot-updates/test.js`
2+
3+
The actual snapshot is saved in `test.js.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## cannot update snapshots when file contains exclusive tests
8+
9+
> failed tests
10+
11+
[]
12+
13+
> passed tests
14+
15+
[
16+
{
17+
file: 'contains-only.js',
18+
title: 'exclusive test',
19+
},
20+
]
21+
22+
> files where snapshots could not be updated
23+
24+
[
25+
{
26+
file: 'contains-only.js',
27+
},
28+
]
29+
30+
## cannot update snapshots when file contains skipped tests
31+
32+
> failed tests
33+
34+
[
35+
{
36+
file: 'contains-skip.js',
37+
title: 'always failing snapshot',
38+
},
39+
]
40+
41+
> skipped tests
42+
43+
[
44+
{
45+
file: 'contains-skip.js',
46+
title: 'skipped test',
47+
},
48+
]
49+
50+
> files where snapshots could not be updated
51+
52+
[
53+
{
54+
file: 'contains-skip.js',
55+
},
56+
]
57+
58+
## cannot update snapshots when matching test titles
59+
60+
> Snapshot 1
61+
62+
'Snapshots cannot be updated when matching specific tests.'
63+
64+
## cannot update snapshots when selecting tests by line number
65+
66+
> Snapshot 1
67+
68+
'Snapshots cannot be updated when selecting specific tests by their line number.'
454 Bytes
Binary file not shown.

‎test/snapshot-updates/test.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const test = require('@ava/test');
2+
const exec = require('../helpers/exec');
3+
4+
test('cannot update snapshots when file contains skipped tests', async t => {
5+
const result = await t.throwsAsync(exec.fixture('contains-skip.js', '-u'));
6+
t.snapshot(result.stats.failed, 'failed tests');
7+
t.snapshot(result.stats.skipped, 'skipped tests');
8+
t.snapshot(result.stats.unsavedSnapshots, 'files where snapshots could not be updated');
9+
});
10+
11+
test('cannot update snapshots when file contains exclusive tests', async t => {
12+
const result = await exec.fixture('contains-only.js', '-u');
13+
t.snapshot(result.stats.failed, 'failed tests');
14+
t.snapshot(result.stats.passed, 'passed tests');
15+
t.snapshot(result.stats.unsavedSnapshots, 'files where snapshots could not be updated');
16+
});
17+
18+
const stripLeadingFigures = string => string.replace(/^\W+/, '');
19+
20+
test('cannot update snapshots when matching test titles', async t => {
21+
const result = await t.throwsAsync(exec.fixture('contains-skip.js', '-u', '-m=snapshot'));
22+
t.snapshot(stripLeadingFigures(result.stderr.trim()));
23+
});
24+
25+
test('cannot update snapshots when selecting tests by line number', async t => {
26+
const result = await t.throwsAsync(exec.fixture('contains-skip.js:4', '-u'));
27+
t.snapshot(stripLeadingFigures(result.stderr.trim()));
28+
});

0 commit comments

Comments
 (0)
Please sign in to comment.