in src/client/testing/testController/unittest/unittestController.ts [108:241]
public async refreshTestData(testController: TestController, uri: Uri, token?: CancellationToken): Promise<void> {
sendTelemetryEvent(EventName.UNITTEST_DISCOVERING, undefined, { tool: 'unittest' });
const workspace = this.workspaceService.getWorkspaceFolder(uri);
if (workspace) {
// Discovery is expensive. So if it is already running then use the promise
// from the last run
const previous = this.discovering.get(workspace.uri.fsPath);
if (previous) {
return previous.promise;
}
const settings = this.configService.getSettings(workspace.uri);
const options: TestDiscoveryOptions = {
workspaceFolder: workspace.uri,
cwd:
settings.testing.cwd && settings.testing.cwd.length > 0
? settings.testing.cwd
: workspace.uri.fsPath,
args: settings.testing.unittestArgs,
ignoreCache: true,
token,
};
const startDir = unittestGetTestFolders(options.args)[0];
const pattern = unittestGetTestPattern(options.args);
let testDir = startDir;
if (path.isAbsolute(startDir)) {
const relative = path.relative(options.cwd, startDir);
testDir = relative.length > 0 ? relative : '.';
}
const runOptions: Options = {
// unittest needs to load modules in the workspace
// isolating it breaks unittest discovery
args: unittestDiscovery([startDir, pattern]),
cwd: options.cwd,
workspaceFolder: options.workspaceFolder,
token: options.token,
outChannel: options.outChannel,
};
const deferred = createDeferred<void>();
this.discovering.set(workspace.uri.fsPath, deferred);
let rawTestData: RawDiscoveredTests | undefined;
try {
const content = await this.discoveryRunner.run(UNITTEST_PROVIDER, runOptions);
rawTestData = await testDiscoveryParser(options.cwd, testDir, getTestIds(content), options.token);
this.testData.set(workspace.uri.fsPath, rawTestData);
const exceptions = getTestDiscoveryExceptions(content);
if (exceptions.length === 0) {
// Remove error node
testController.items.delete(`DiscoveryError:${workspace.uri.fsPath}`);
} else {
traceError('Error discovering unittest tests:\r\n', exceptions.join('\r\n\r\n'));
let errorNode = testController.items.get(`DiscoveryError:${workspace.uri.fsPath}`);
const message = util.format(
'Error discovering unittest tests (see Output > Python):\r\n',
exceptions.join('\r\n\r\n'),
);
if (errorNode === undefined) {
errorNode = createErrorTestItem(testController, {
id: `DiscoveryError:${workspace.uri.fsPath}`,
label: `Unittest Discovery Error [${path.basename(workspace.uri.fsPath)}]`,
error: message,
});
errorNode.canResolveChildren = false;
testController.items.add(errorNode);
}
errorNode.error = message;
}
deferred.resolve();
} catch (ex) {
sendTelemetryEvent(EventName.UNITTEST_DISCOVERY_DONE, undefined, { tool: 'unittest', failed: true });
const cancel = options.token?.isCancellationRequested ? 'Cancelled' : 'Error';
traceError(`${cancel} discovering unittest tests:\r\n`, ex);
// Report also on the test view.
testController.items.add(
createErrorTestItem(testController, {
id: `DiscoveryError:${workspace.uri.fsPath}`,
label: `Unittest Discovery Error [${path.basename(workspace.uri.fsPath)}]`,
error: util.format(`${cancel} discovering unittest tests (see Output > Python):\r\n`, ex),
}),
);
deferred.reject(ex as Error);
} finally {
// Discovery has finished running we have the raw test data at this point.
this.discovering.delete(workspace.uri.fsPath);
}
if (!rawTestData) {
// No test data is available
return Promise.resolve();
}
const workspaceNode = testController.items.get(rawTestData.root);
if (workspaceNode) {
if (uri.fsPath === workspace.uri.fsPath) {
// this is a workspace level refresh
// This is an existing workspace test node. Just update the children
await this.resolveChildren(testController, workspaceNode, token);
} else {
// This is a child node refresh
const testNode = getNodeByUri(workspaceNode, uri);
if (testNode) {
// We found the node to update
await this.resolveChildren(testController, testNode, token);
} else {
// update the entire workspace tree
await this.resolveChildren(testController, workspaceNode, token);
}
}
} else if (rawTestData.tests.length > 0) {
// This is a new workspace with tests.
const newItem = createWorkspaceRootTestItem(testController, this.idToRawData, {
id: rawTestData.root,
label: path.basename(rawTestData.root),
uri: Uri.file(rawTestData.root),
runId: rawTestData.root === '.' ? workspace.uri.fsPath : rawTestData.root,
rawId: rawTestData.rootid,
});
testController.items.add(newItem);
await this.resolveChildren(testController, newItem, token);
}
}
sendTelemetryEvent(EventName.UNITTEST_DISCOVERY_DONE, undefined, { tool: 'unittest', failed: false });
return Promise.resolve();
}