Skip to content

Commit 5a075dc

Browse files
authored
Tests - Add more logging to test runner utility (#1882)
* Tests - Add more logging to test runner utility Occasionally the tests that use the `runTest` utility method to test running tests in VS Code will time out. Add more logging to help pinpoint the issue. Increase the timeout for the test explorer integration tests on windows, as sourcekit-lsp can take > 10 minutes to index on 6.0
1 parent 021b645 commit 5a075dc

File tree

5 files changed

+58
-48
lines changed

5 files changed

+58
-48
lines changed

assets/test/.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"-Xswiftc",
88
"-DTEST_ARGUMENT_SET_VIA_TEST_BUILD_ARGUMENTS_SETTING"
99
],
10+
"swift.outputChannelLogLevel": "debug",
1011
"lldb.verboseLogging": true,
1112
"lldb.launch.terminal": "external",
1213
"lldb-dap.detachOnError": true,

src/TestExplorer/TestExplorer.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ export class TestExplorer {
280280
tests: TestDiscovery.TestClass[],
281281
uri?: vscode.Uri
282282
) {
283+
this.logger.debug("Updating tests in test explorer", "Test Discovery");
283284
TestDiscovery.updateTests(controller, tests, uri);
284285
this.onTestItemsDidChangeEmitter.fire(controller);
285286
}
@@ -382,6 +383,10 @@ export class TestExplorer {
382383
explorer.deleteErrorTestItem();
383384

384385
const tests = parseTestsFromSwiftTestListOutput(stdout);
386+
this.logger.debug(
387+
`Discovered ${tests.length} top level tests via 'swift test --list-tests', updating test explorer`,
388+
"Test Discovery"
389+
);
385390
explorer.updateTests(explorer.controller, tests);
386391
}
387392
);
@@ -438,18 +443,33 @@ export class TestExplorer {
438443
* Discover tests
439444
*/
440445
private async discoverTestsInWorkspaceLSP(token: vscode.CancellationToken) {
446+
this.logger.debug("Discovering tests in workspace via LSP", "Test Discovery");
447+
441448
const tests = await this.lspTestDiscovery.getWorkspaceTests(
442449
this.folderContext.swiftPackage
443450
);
451+
444452
if (token.isCancellationRequested) {
453+
this.logger.info("Test discovery cancelled", "Test Discovery");
445454
return;
446455
}
447456

457+
this.logger.debug(
458+
`Discovered ${tests.length} top level tests, updating test explorer`,
459+
"Test Discovery"
460+
);
461+
448462
await TestDiscovery.updateTestsFromClasses(
449463
this.controller,
450464
this.folderContext.swiftPackage,
451465
tests
452466
);
467+
468+
this.logger.debug(
469+
"Emitting test item change after LSP workspace test discovery",
470+
"Test Discovery"
471+
);
472+
453473
this.onTestItemsDidChangeEmitter.fire(this.controller);
454474
}
455475

src/logging/RollingLogTransport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const Transport: typeof TransportType = require("winston-transport");
2222
export class RollingLogTransport extends Transport {
2323
constructor(private rollingLog: RollingLog) {
2424
super();
25-
this.level = "info"; // This log is used for testing, we don't want to hold verbose log messages
25+
this.level = "debug";
2626
}
2727

2828
// eslint-disable-next-line @typescript-eslint/no-explicit-any

test/integration-tests/testexplorer/TestExplorerIntegration.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ tag("large").suite("Test Explorer Suite", function () {
6666

6767
activateExtensionForSuite({
6868
async setup(ctx) {
69+
// It can take a very long time for sourcekit-lsp to index tests on Windows,
70+
// especially w/ Swift 6.0. Wait for up to 25 minutes for the indexing to complete.
71+
if (process.platform === "win32") {
72+
this.timeout(25 * 60 * 1000);
73+
}
74+
6975
workspaceContext = ctx;
7076
runTest = runTestWithLogging.bind(null, workspaceContext.logger);
7177
const logger = withLogging(ctx.logger);
@@ -89,7 +95,7 @@ tag("large").suite("Test Explorer Suite", function () {
8995
// Set up the listener before bringing the text explorer in to focus,
9096
// which starts searching the workspace for tests.
9197
await logger("Waiting for test explorer to be ready", () =>
92-
waitForTestExplorerReady(testExplorer)
98+
waitForTestExplorerReady(testExplorer, workspaceContext.logger)
9399
);
94100
},
95101
requiresLSP: true,

test/integration-tests/testexplorer/utilities.ts

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,46 +21,9 @@ import { reduceTestItemChildren } from "@src/TestExplorer/TestUtils";
2121
import { WorkspaceContext } from "@src/WorkspaceContext";
2222
import { SwiftLogger } from "@src/logging/SwiftLogger";
2323

24-
import { testAssetUri } from "../../fixtures";
25-
import {
26-
SettingsMap,
27-
activateExtension,
28-
deactivateExtension,
29-
updateSettings,
30-
} from "../utilities/testutilities";
31-
3224
// eslint-disable-next-line @typescript-eslint/no-require-imports
3325
import stripAnsi = require("strip-ansi");
3426

35-
/**
36-
* Sets up a test that leverages the TestExplorer, returning the TestExplorer,
37-
* WorkspaceContext and a callback to revert the settings back to their original values.
38-
* @param settings Optional extension settings to set before the test starts.
39-
* @returns Object containing the TestExplorer, WorkspaceContext and a callback to revert
40-
* the settings back to their original values.
41-
*/
42-
export async function setupTestExplorerTest(currentTest?: Mocha.Test, settings: SettingsMap = {}) {
43-
const settingsTeardown = await updateSettings(settings);
44-
45-
const testProject = testAssetUri("defaultPackage");
46-
47-
const workspaceContext = await activateExtension(currentTest);
48-
const testExplorer = testExplorerFor(workspaceContext, testProject);
49-
50-
// Set up the listener before bringing the text explorer in to focus,
51-
// which starts searching the workspace for tests.
52-
await waitForTestExplorerReady(testExplorer);
53-
54-
return {
55-
settingsTeardown: async () => {
56-
await settingsTeardown();
57-
await deactivateExtension();
58-
},
59-
workspaceContext,
60-
testExplorer,
61-
};
62-
}
63-
6427
/**
6528
* Returns the TestExplorer for the given workspace and package folder.
6629
*
@@ -215,10 +178,15 @@ export function eventPromise<T>(event: vscode.Event<T>): Promise<T> {
215178
* @returns The initialized test controller
216179
*/
217180
export async function waitForTestExplorerReady(
218-
testExplorer: TestExplorer
181+
testExplorer: TestExplorer,
182+
logger: SwiftLogger
219183
): Promise<vscode.TestController> {
220184
await vscode.commands.executeCommand("workbench.view.testing.focus");
221-
const controller = await (testExplorer.controller.items.size === 0
185+
const noExistingTests = testExplorer.controller.items.size === 0;
186+
logger.info(
187+
`waitForTestExplorerReady: Found ${testExplorer.controller.items.size} existing top level test(s)`
188+
);
189+
const controller = await (noExistingTests
222190
? eventPromise(testExplorer.onTestItemsDidChange)
223191
: Promise.resolve(testExplorer.controller));
224192
return controller;
@@ -311,22 +279,37 @@ export async function runTest(
311279
const testItems = gatherTests(testExplorer.controller, ...tests);
312280
const request = new vscode.TestRunRequest(testItems);
313281

314-
logger.info(`runTest: configuring test run with ${testItems}`);
282+
logger.info(`runTest: configuring test run with ${testItems.map(t => t.id)}`);
315283

316284
// The first promise is the return value, the second promise builds and runs
317285
// the tests, populating the TestRunProxy with results and blocking the return
318286
// of that TestRunProxy until the test run is complete.
319287
return (
320288
await Promise.all([
321289
eventPromise(testExplorer.onCreateTestRun).then(run => {
322-
logger.info(`runTest: created test run with items ${run.testItems}`);
290+
logger.info(`runTest: created test run with items ${run.testItems.map(t => t.id)}`);
323291
return run;
324292
}),
325-
targetProfile
326-
.runHandler(request, new vscode.CancellationTokenSource().token)
327-
?.then(() => {
328-
logger.info(`runTest: completed running tests`);
329-
}),
293+
performRun(targetProfile, request, logger),
330294
])
331295
)[0];
332296
}
297+
298+
async function performRun(
299+
targetProfile: vscode.TestRunProfile,
300+
request: vscode.TestRunRequest,
301+
logger: SwiftLogger
302+
): Promise<void> {
303+
const run = targetProfile.runHandler(request, new vscode.CancellationTokenSource().token);
304+
if (!run) {
305+
throw new Error("No test run was created");
306+
}
307+
logger.info(`runTest: starting running tests`);
308+
try {
309+
await run;
310+
logger.info(`runTest: completed running tests`);
311+
} catch (e) {
312+
logger.error(`runTest: error running tests: ${e}`);
313+
throw e;
314+
}
315+
}

0 commit comments

Comments
 (0)