in src/controller/testController.ts [137:241]
export const runTests: (request: TestRunRequest, option: IRunOption) => any = instrumentOperation('java.test.runTests', async (operationId: string, request: TestRunRequest, option: IRunOption) => {
sendInfo(operationId, {
isDebug: `${option.isDebug}`,
});
const testItems: TestItem[] = await new Promise<TestItem[]>(async (resolve: (result: TestItem[]) => void): Promise<void> => {
option.progressReporter = option.progressReporter ?? progressProvider?.createProgressReporter(option.isDebug ? 'Debug Tests' : 'Run Tests');
option.token?.onCancellationRequested(() => {
option.progressReporter?.done();
return resolve([]);
});
const progressToken: CancellationToken | undefined = option.progressReporter?.getCancellationToken();
option.onProgressCancelHandler = progressToken?.onCancellationRequested(() => {
option.progressReporter?.done();
return resolve([]);
});
option.progressReporter?.report('Searching tests...');
const result: TestItem[] = await getIncludedItems(request, progressToken);
await expandTests(result, TestLevel.Method, progressToken);
return resolve(result);
});
if (testItems.length === 0) {
option.progressReporter?.done();
return;
}
const run: TestRun = testController!.createTestRun(request);
try {
await new Promise<void>(async (resolve: () => void): Promise<void> => {
const token: CancellationToken = option.token ?? run.token;
token.onCancellationRequested(() => {
option.progressReporter?.done();
run.end();
return resolve();
});
enqueueTestMethods(testItems, run);
const queue: TestItem[][] = mergeTestMethods(testItems);
for (const testsInQueue of queue) {
if (testsInQueue.length === 0) {
continue;
}
const testProjectMapping: Map<string, TestItem[]> = mapTestItemsByProject(testsInQueue);
for (const [projectName, itemsPerProject] of testProjectMapping.entries()) {
const testKindMapping: Map<TestKind, TestItem[]> = mapTestItemsByKind(itemsPerProject);
for (const [kind, items] of testKindMapping.entries()) {
if (option.progressReporter?.isCancelled()) {
option.progressReporter = progressProvider?.createProgressReporter(option.isDebug ? 'Debug Tests' : 'Run Tests');
}
let delegatedToDebugger: boolean = false;
option.onProgressCancelHandler?.dispose();
option.progressReporter?.getCancellationToken().onCancellationRequested(() => {
if (delegatedToDebugger) {
// If the progress reporter has been delegated to debugger, a cancellation event
// might be emitted due to debug session finished, thus we will ignore such event.
return;
}
option.progressReporter?.done();
return resolve();
});
option.progressReporter?.report('Resolving launch configuration...');
// TODO: improve the config experience
const workspaceFolder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(items[0].uri!);
if (!workspaceFolder) {
window.showErrorMessage(`Failed to get workspace folder from test item: ${items[0].label}.`);
continue;
}
const config: IExecutionConfig | undefined = await loadRunConfig(workspaceFolder);
if (!config) {
continue;
}
const testContext: IRunTestContext = {
isDebug: option.isDebug,
kind,
projectName,
testItems: items,
testRun: run,
workspaceFolder,
};
sendInfo(operationId, {
testFramework: TestKind[testContext.kind],
});
const runner: BaseRunner | undefined = getRunnerByContext(testContext);
if (!runner) {
window.showErrorMessage(`Failed to get suitable runner for the test kind: ${testContext.kind}.`);
continue;
}
try {
await runner.setup();
const resolvedConfiguration: DebugConfiguration = option.launchConfiguration ?? await resolveLaunchConfigurationForRunner(runner, testContext, config);
resolvedConfiguration.__progressId = option.progressReporter?.getId();
delegatedToDebugger = true;
await runner.run(resolvedConfiguration, token, option.progressReporter);
} finally {
await runner.tearDown();
}
}
}
}
return resolve();
});
} finally {
run.end();
}
});