forked from microsoft/vscode-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrunner.ts
More file actions
127 lines (112 loc) · 5.05 KB
/
runner.ts
File metadata and controls
127 lines (112 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use strict';
import { inject, injectable } from 'inversify';
import { IFileSystem, TemporaryFile } from '../../common/platform/types';
import { noop } from '../../common/utils/misc';
import { IServiceContainer } from '../../ioc/types';
import { PYTEST_PROVIDER } from '../common/constants';
import { Options } from '../common/runner';
import {
IArgumentsHelper,
IArgumentsService,
ITestDebugLauncher,
ITestManagerRunner,
ITestResultsService,
ITestRunner,
IXUnitParser,
LaunchOptions,
TestRunOptions,
Tests,
} from '../common/types';
const JunitXmlArgOld = '--junitxml';
const JunitXmlArg = '--junit-xml';
@injectable()
export class TestManagerRunner implements ITestManagerRunner {
private readonly argsService: IArgumentsService;
private readonly argsHelper: IArgumentsHelper;
private readonly testRunner: ITestRunner;
private readonly xUnitParser: IXUnitParser;
private readonly fs: IFileSystem;
constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
this.argsService = serviceContainer.get<IArgumentsService>(IArgumentsService, PYTEST_PROVIDER);
this.argsHelper = serviceContainer.get<IArgumentsHelper>(IArgumentsHelper);
this.testRunner = serviceContainer.get<ITestRunner>(ITestRunner);
this.xUnitParser = this.serviceContainer.get<IXUnitParser>(IXUnitParser);
this.fs = this.serviceContainer.get<IFileSystem>(IFileSystem);
}
public async runTest(
testResultsService: ITestResultsService,
options: TestRunOptions,
// We ignore the ITestManager arg,
): Promise<Tests> {
let testPaths: string[] = [];
if (options.testsToRun && options.testsToRun.testFolder) {
testPaths = testPaths.concat(options.testsToRun.testFolder.map((f) => f.nameToRun));
}
if (options.testsToRun && options.testsToRun.testFile) {
testPaths = testPaths.concat(options.testsToRun.testFile.map((f) => f.nameToRun));
}
if (options.testsToRun && options.testsToRun.testSuite) {
testPaths = testPaths.concat(options.testsToRun.testSuite.map((f) => f.nameToRun));
}
if (options.testsToRun && options.testsToRun.testFunction) {
testPaths = testPaths.concat(options.testsToRun.testFunction.map((f) => f.nameToRun));
}
let deleteJUnitXmlFile: () => void = noop;
const { args } = options;
try {
const xmlLogResult = await this.getJUnitXmlFile(args);
const xmlLogFile = xmlLogResult.filePath;
deleteJUnitXmlFile = xmlLogResult.dispose;
// Remove the '--junitxml' or '--junit-xml' if it exists, and add it with our path.
const testArgs = this.argsService.filterArguments(args, [JunitXmlArg, JunitXmlArgOld]);
testArgs.splice(0, 0, `${JunitXmlArg}=${xmlLogFile}`);
testArgs.splice(0, 0, '--rootdir', options.workspaceFolder.fsPath);
testArgs.splice(0, 0, '--override-ini', 'junit_family=xunit1');
// Positional arguments control the tests to be run.
testArgs.push(...testPaths);
if (options.debug) {
const debugLauncher = this.serviceContainer.get<ITestDebugLauncher>(ITestDebugLauncher);
const debuggerArgs = [options.cwd, 'pytest'].concat(testArgs);
const launchOptions: LaunchOptions = {
cwd: options.cwd,
args: debuggerArgs,
token: options.token,
outChannel: options.outChannel,
testProvider: PYTEST_PROVIDER,
};
await debugLauncher.launchDebugger(launchOptions);
} else {
const runOptions: Options = {
args: testArgs,
cwd: options.cwd,
outChannel: options.outChannel,
token: options.token,
workspaceFolder: options.workspaceFolder,
};
await this.testRunner.run(PYTEST_PROVIDER, runOptions);
}
// Promise must resolve before return as result file will be deleted in finally block.
return await this.updateResultsFromLogFiles(options.tests, xmlLogFile, testResultsService);
} catch (ex) {
return Promise.reject<Tests>(ex);
} finally {
deleteJUnitXmlFile();
}
}
private async updateResultsFromLogFiles(
tests: Tests,
outputXmlFile: string,
testResultsService: ITestResultsService,
): Promise<Tests> {
await this.xUnitParser.updateResultsFromXmlLogFile(tests, outputXmlFile);
testResultsService.updateResults(tests);
return tests;
}
private async getJUnitXmlFile(args: string[]): Promise<TemporaryFile> {
const xmlFile = this.argsHelper.getOptionValues(args, JunitXmlArg);
if (typeof xmlFile === 'string') {
return { filePath: xmlFile, dispose: noop };
}
return this.fs.createTemporaryFile('.xml');
}
}