Skip to content

Commit 5572877

Browse files
authored
Mark tests as skipped when they fail to compile (#1659)
1 parent ab9e74e commit 5572877

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- Capture diagnostics with `Swift: Capture Diagnostic Bundle` to a .zip file ([#1656](https://github.com/swiftlang/vscode-swift/pull/1656))
1010
- Prevent continuous "package resolve" cycles ([#1654](https://github.com/swiftlang/vscode-swift/pull/1654))
1111
- Fix error when running `Reset Package Dependencies` command from the Project view ([#1661](https://github.com/swiftlang/vscode-swift/pull/1661))
12+
- Mark tests as skipped when a compilation error preempts a test run ([#1659](https://github.com/swiftlang/vscode-swift/pull/1659))
1213

1314
## 2.6.0 - 2025-06-26
1415

src/TestExplorer/TestRunner.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ import * as stream from "stream";
1818
import * as os from "os";
1919
import * as asyncfs from "fs/promises";
2020
import { FolderContext } from "../FolderContext";
21-
import { compactMap, execFile, getErrorDescription } from "../utilities/utilities";
21+
import {
22+
compactMap,
23+
execFile,
24+
getErrorDescription,
25+
IS_PRODUCTION_BUILD,
26+
} from "../utilities/utilities";
2227
import { createSwiftTask } from "../tasks/SwiftTaskProvider";
2328
import configuration from "../configuration";
2429
import { WorkspaceContext } from "../WorkspaceContext";
@@ -67,6 +72,7 @@ export interface TestRunState {
6772
passed: vscode.TestItem[];
6873
skipped: vscode.TestItem[];
6974
errored: vscode.TestItem[];
75+
enqueued: vscode.TestItem[];
7076
unknown: number;
7177
output: string[];
7278
}
@@ -95,6 +101,7 @@ export class TestRunProxy {
95101
passed: [],
96102
skipped: [],
97103
errored: [],
104+
enqueued: [],
98105
unknown: 0,
99106
output: [],
100107
};
@@ -181,10 +188,9 @@ export class TestRunProxy {
181188
for (const outputLine of this.queuedOutput) {
182189
this.performAppendOutput(this.testRun, outputLine);
183190
}
184-
this.queuedOutput = [];
185191

186192
for (const test of this.testItems) {
187-
this.testRun.enqueued(test);
193+
this.enqueued(test);
188194
}
189195
};
190196

@@ -218,11 +224,17 @@ export class TestRunProxy {
218224
}
219225
}
220226

227+
private enqueued(test: vscode.TestItem) {
228+
this.testRun?.enqueued(test);
229+
this.runState.enqueued.push(test);
230+
}
231+
221232
public unknownTestRan() {
222233
this.runState.unknown++;
223234
}
224235

225236
public started(test: vscode.TestItem) {
237+
this.clearEnqueuedTest(test);
226238
this.runState.pending.push(test);
227239
this.testRun?.started(test);
228240
}
@@ -231,7 +243,29 @@ export class TestRunProxy {
231243
this.runState.pending = this.runState.pending.filter(t => t !== test);
232244
}
233245

246+
private clearEnqueuedTest(test: vscode.TestItem) {
247+
if (IS_PRODUCTION_BUILD) {
248+
// `runState.enqueued` exists only for test validation purposes.
249+
return;
250+
}
251+
252+
this.runState.enqueued = this.runState.enqueued.filter(t => t !== test);
253+
254+
if (!test.parent) {
255+
return;
256+
}
257+
258+
const parentHasEnqueuedChildren = Array.from(test.parent.children).some(([_, child]) =>
259+
this.runState.enqueued.includes(child)
260+
);
261+
262+
if (!parentHasEnqueuedChildren) {
263+
this.clearEnqueuedTest(test.parent);
264+
}
265+
}
266+
234267
public skipped(test: vscode.TestItem) {
268+
this.clearEnqueuedTest(test);
235269
test.tags = [...test.tags, new vscode.TestTag(TestRunProxy.Tags.SKIPPED)];
236270

237271
this.runState.skipped.push(test);
@@ -240,6 +274,7 @@ export class TestRunProxy {
240274
}
241275

242276
public passed(test: vscode.TestItem, duration?: number) {
277+
this.clearEnqueuedTest(test);
243278
this.runState.passed.push(test);
244279
this.clearPendingTest(test);
245280
this.testRun?.passed(test, duration);
@@ -250,6 +285,7 @@ export class TestRunProxy {
250285
message: vscode.TestMessage | readonly vscode.TestMessage[],
251286
duration?: number
252287
) {
288+
this.clearEnqueuedTest(test);
253289
this.runState.failed.push({ test, message });
254290
this.clearPendingTest(test);
255291
this.testRun?.failed(test, message, duration);
@@ -260,6 +296,7 @@ export class TestRunProxy {
260296
message: vscode.TestMessage | readonly vscode.TestMessage[],
261297
duration?: number
262298
) {
299+
this.clearEnqueuedTest(test);
263300
this.runState.errored.push(test);
264301
this.clearPendingTest(test);
265302
this.testRun?.errored(test, message, duration);
@@ -278,6 +315,21 @@ export class TestRunProxy {
278315
this.failed(test, new vscode.TestMessage("Test did not complete."));
279316
});
280317

318+
// If there are tests that never started, mark them as skipped.
319+
// This can happen if there is a build error preventing tests from running.
320+
this.runState.enqueued.forEach(test => {
321+
// Omit adding the root test item as a skipped test to keep just the suites/tests
322+
// in the test run output, just like a regular pass/fail test run.
323+
if (test.parent) {
324+
for (const output of this.queuedOutput) {
325+
this.appendOutputToTest(output, test);
326+
}
327+
this.skipped(test);
328+
}
329+
});
330+
331+
this.queuedOutput = [];
332+
281333
this.reportAttachments();
282334
this.testRun?.end();
283335
this.testRunCompleteEmitter.fire();

test/integration-tests/testexplorer/utilities.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export function assertTestResults(
145145
passed?: string[];
146146
skipped?: string[];
147147
errored?: string[];
148+
enqueued?: string[];
148149
unknown?: number;
149150
}
150151
) {
@@ -161,6 +162,7 @@ export function assertTestResults(
161162
.sort(),
162163
skipped: testRun.runState.skipped.map(({ id }) => id).sort(),
163164
errored: testRun.runState.errored.map(({ id }) => id).sort(),
165+
enqueued: testRun.runState.enqueued.map(({ id }) => id).sort(),
164166
unknown: testRun.runState.unknown,
165167
},
166168
{
@@ -173,6 +175,7 @@ export function assertTestResults(
173175
.sort(),
174176
skipped: (state.skipped ?? []).sort(),
175177
errored: (state.errored ?? []).sort(),
178+
enqueued: (state.enqueued ?? []).sort(),
176179
unknown: 0,
177180
},
178181
`

0 commit comments

Comments
 (0)