Skip to content

Commit 9c88db8

Browse files
committed
exec object
1 parent 0e3cc19 commit 9c88db8

File tree

6 files changed

+64
-61
lines changed

6 files changed

+64
-61
lines changed

src/client/testing/testController/common/types.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,12 @@ export interface ITestDiscoveryAdapter {
167167

168168
// interface for execution/runner adapter
169169
export interface ITestExecutionAdapter {
170-
// ** first line old method signature, second line new method signature
171-
runTests(uri: Uri, testIds: string[], profileKind?: boolean | TestRunProfileKind): Promise<void>;
172170
runTests(
173171
uri: Uri,
174172
testIds: string[],
175-
profileKind?: boolean | TestRunProfileKind,
176-
runInstance?: TestRun,
177-
executionFactory?: IPythonExecutionFactory,
173+
profileKind: boolean | TestRunProfileKind | undefined,
174+
runInstance: TestRun,
175+
executionFactory: IPythonExecutionFactory,
178176
debugLauncher?: ITestDebugLauncher,
179177
interpreter?: PythonEnvironment,
180178
): Promise<void>;

src/client/testing/testController/controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,9 @@ export class PythonTestController implements ITestController, IExtensionSingleAc
453453
this.testController,
454454
runInstance,
455455
testItems,
456+
this.pythonExecFactory,
456457
token,
457458
request.profile?.kind,
458-
this.pythonExecFactory,
459459
this.debugLauncher,
460460
await this.interpreterService.getActiveInterpreter(workspace.uri),
461461
);
@@ -470,9 +470,9 @@ export class PythonTestController implements ITestController, IExtensionSingleAc
470470
this.testController,
471471
runInstance,
472472
testItems,
473+
this.pythonExecFactory,
473474
token,
474475
request.profile?.kind,
475-
this.pythonExecFactory,
476476
this.debugLauncher,
477477
await this.interpreterService.getActiveInterpreter(workspace.uri),
478478
);

src/client/testing/testController/pytest/pytestExecutionAdapter.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
3232
async runTests(
3333
uri: Uri,
3434
testIds: string[],
35-
profileKind?: TestRunProfileKind,
36-
runInstance?: TestRun,
37-
executionFactory?: IPythonExecutionFactory,
35+
profileKind: boolean | TestRunProfileKind | undefined,
36+
runInstance: TestRun,
37+
executionFactory: IPythonExecutionFactory,
3838
debugLauncher?: ITestDebugLauncher,
3939
interpreter?: PythonEnvironment,
4040
): Promise<void> {
@@ -49,14 +49,14 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
4949
}
5050
};
5151
const cSource = new CancellationTokenSource();
52-
runInstance?.token.onCancellationRequested(() => cSource.cancel());
52+
runInstance.token.onCancellationRequested(() => cSource.cancel());
5353

5454
const name = await utils.startRunResultNamedPipe(
5555
dataReceivedCallback, // callback to handle data received
5656
deferredTillServerClose, // deferred to resolve when server closes
5757
cSource.token, // token to cancel
5858
);
59-
runInstance?.token.onCancellationRequested(() => {
59+
runInstance.token.onCancellationRequested(() => {
6060
traceInfo(`Test run cancelled, resolving 'TillServerClose' deferred for ${uri.fsPath}.`);
6161
});
6262

@@ -82,9 +82,9 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
8282
testIds: string[],
8383
resultNamedPipeName: string,
8484
serverCancel: CancellationTokenSource,
85-
runInstance?: TestRun,
86-
profileKind?: TestRunProfileKind,
87-
executionFactory?: IPythonExecutionFactory,
85+
runInstance: TestRun,
86+
profileKind: boolean | TestRunProfileKind | undefined,
87+
executionFactory: IPythonExecutionFactory,
8888
debugLauncher?: ITestDebugLauncher,
8989
interpreter?: PythonEnvironment,
9090
): Promise<ExecutionTestPayload> {
@@ -114,7 +114,7 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
114114
interpreter,
115115
};
116116
// need to check what will happen in the exec service is NOT defined and is null
117-
const execService = await executionFactory?.createActivatedEnvironment(creationOptions);
117+
const execService = await executionFactory.createActivatedEnvironment(creationOptions);
118118

119119
const execInfo = await execService?.getExecutablePath();
120120
traceVerbose(`Executable path for pytest execution: ${execInfo}.`);
@@ -144,14 +144,14 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
144144
cwd,
145145
throwOnStdErr: true,
146146
env: mutableEnv,
147-
token: runInstance?.token,
147+
token: runInstance.token,
148148
};
149149

150150
if (debugBool) {
151151
const launchOptions: LaunchOptions = {
152152
cwd,
153153
args: testArgs,
154-
token: runInstance?.token,
154+
token: runInstance.token,
155155
testProvider: PYTEST_PROVIDER,
156156
runTestIdsPort: testIdsFileName,
157157
pytestPort: resultNamedPipeName,
@@ -181,19 +181,19 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
181181
args: runArgs,
182182
env: (mutableEnv as unknown) as { [key: string]: string },
183183
});
184-
runInstance?.token.onCancellationRequested(() => {
184+
runInstance.token.onCancellationRequested(() => {
185185
traceInfo(`Test run cancelled, killing pytest subprocess for workspace ${uri.fsPath}`);
186186
proc.kill();
187187
deferredTillExecClose.resolve();
188188
serverCancel.cancel();
189189
});
190190
proc.stdout.on('data', (data) => {
191191
const out = utils.fixLogLinesNoTrailing(data.toString());
192-
runInstance?.appendOutput(out);
192+
runInstance.appendOutput(out);
193193
});
194194
proc.stderr.on('data', (data) => {
195195
const out = utils.fixLogLinesNoTrailing(data.toString());
196-
runInstance?.appendOutput(out);
196+
runInstance.appendOutput(out);
197197
});
198198
proc.onExit((code, signal) => {
199199
if (code !== 0) {
@@ -218,7 +218,7 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
218218

219219
let resultProc: ChildProcess | undefined;
220220

221-
runInstance?.token.onCancellationRequested(() => {
221+
runInstance.token.onCancellationRequested(() => {
222222
traceInfo(`Test run cancelled, killing pytest subprocess for workspace ${uri.fsPath}`);
223223
// if the resultProc exists just call kill on it which will handle resolving the ExecClose deferred, otherwise resolve the deferred here.
224224
if (resultProc) {
@@ -235,11 +235,11 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
235235
// Displays output to user and ensure the subprocess doesn't run into buffer overflow.
236236
result?.proc?.stdout?.on('data', (data) => {
237237
const out = utils.fixLogLinesNoTrailing(data.toString());
238-
runInstance?.appendOutput(out);
238+
runInstance.appendOutput(out);
239239
});
240240
result?.proc?.stderr?.on('data', (data) => {
241241
const out = utils.fixLogLinesNoTrailing(data.toString());
242-
runInstance?.appendOutput(out);
242+
runInstance.appendOutput(out);
243243
});
244244
result?.proc?.on('exit', (code, signal) => {
245245
if (code !== 0) {

src/client/testing/testController/unittest/testExecutionAdapter.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
4242
public async runTests(
4343
uri: Uri,
4444
testIds: string[],
45-
profileKind?: TestRunProfileKind,
46-
runInstance?: TestRun,
47-
executionFactory?: IPythonExecutionFactory,
45+
profileKind: boolean | TestRunProfileKind | undefined,
46+
runInstance: TestRun,
47+
executionFactory: IPythonExecutionFactory,
4848
debugLauncher?: ITestDebugLauncher,
4949
): Promise<void> {
5050
// deferredTillServerClose awaits named pipe server close
@@ -59,13 +59,13 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
5959
}
6060
};
6161
const cSource = new CancellationTokenSource();
62-
runInstance?.token.onCancellationRequested(() => cSource.cancel());
62+
runInstance.token.onCancellationRequested(() => cSource.cancel());
6363
const name = await utils.startRunResultNamedPipe(
6464
dataReceivedCallback, // callback to handle data received
6565
deferredTillServerClose, // deferred to resolve when server closes
6666
cSource.token, // token to cancel
6767
);
68-
runInstance?.token.onCancellationRequested(() => {
68+
runInstance.token.onCancellationRequested(() => {
6969
console.log(`Test run cancelled, resolving 'till TillAllServerClose' deferred for ${uri.fsPath}.`);
7070
// if canceled, stop listening for results
7171
deferredTillServerClose.resolve();
@@ -93,9 +93,9 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
9393
testIds: string[],
9494
resultNamedPipeName: string,
9595
serverCancel: CancellationTokenSource,
96-
runInstance?: TestRun,
97-
profileKind?: TestRunProfileKind,
98-
executionFactory?: IPythonExecutionFactory,
96+
runInstance: TestRun,
97+
profileKind: boolean | TestRunProfileKind | undefined,
98+
executionFactory: IPythonExecutionFactory,
9999
debugLauncher?: ITestDebugLauncher,
100100
): Promise<ExecutionTestPayload> {
101101
const settings = this.configSettings.getSettings(uri);
@@ -119,9 +119,9 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
119119
workspaceFolder: uri,
120120
command,
121121
cwd,
122-
profileKind,
122+
profileKind: typeof profileKind === 'boolean' ? undefined : profileKind,
123123
testIds,
124-
token: runInstance?.token,
124+
token: runInstance.token,
125125
};
126126
traceLog(`Running UNITTEST execution for the following test ids: ${testIds}`);
127127

@@ -145,7 +145,7 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
145145
allowEnvironmentFetchExceptions: false,
146146
resource: options.workspaceFolder,
147147
};
148-
const execService = await executionFactory?.createActivatedEnvironment(creationOptions);
148+
const execService = await executionFactory.createActivatedEnvironment(creationOptions);
149149

150150
const execInfo = await execService?.getExecutablePath();
151151
traceVerbose(`Executable path for unittest execution: ${execInfo}.`);
@@ -193,19 +193,19 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
193193
args,
194194
env: (mutableEnv as unknown) as { [key: string]: string },
195195
});
196-
runInstance?.token.onCancellationRequested(() => {
196+
runInstance.token.onCancellationRequested(() => {
197197
traceInfo(`Test run cancelled, killing unittest subprocess for workspace ${uri.fsPath}`);
198198
proc.kill();
199199
deferredTillExecClose.resolve();
200200
serverCancel.cancel();
201201
});
202202
proc.stdout.on('data', (data) => {
203203
const out = utils.fixLogLinesNoTrailing(data.toString());
204-
runInstance?.appendOutput(out);
204+
runInstance.appendOutput(out);
205205
});
206206
proc.stderr.on('data', (data) => {
207207
const out = utils.fixLogLinesNoTrailing(data.toString());
208-
runInstance?.appendOutput(out);
208+
runInstance.appendOutput(out);
209209
});
210210
proc.onExit((code, signal) => {
211211
if (code !== 0) {
@@ -228,7 +228,7 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
228228

229229
let resultProc: ChildProcess | undefined;
230230

231-
runInstance?.token.onCancellationRequested(() => {
231+
runInstance.token.onCancellationRequested(() => {
232232
traceInfo(`Test run cancelled, killing unittest subprocess for workspace ${cwd}.`);
233233
// if the resultProc exists just call kill on it which will handle resolving the ExecClose deferred, otherwise resolve the deferred here.
234234
if (resultProc) {
@@ -246,11 +246,11 @@ export class UnittestTestExecutionAdapter implements ITestExecutionAdapter {
246246

247247
result?.proc?.stdout?.on('data', (data) => {
248248
const out = fixLogLinesNoTrailing(data.toString());
249-
runInstance?.appendOutput(`${out}`);
249+
runInstance.appendOutput(`${out}`);
250250
});
251251
result?.proc?.stderr?.on('data', (data) => {
252252
const out = fixLogLinesNoTrailing(data.toString());
253-
runInstance?.appendOutput(`${out}`);
253+
runInstance.appendOutput(`${out}`);
254254
});
255255

256256
result?.proc?.on('exit', (code, signal) => {

src/client/testing/testController/workspaceTestAdapter.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ export class WorkspaceTestAdapter {
4242
testController: TestController,
4343
runInstance: TestRun,
4444
includes: TestItem[],
45+
executionFactory: IPythonExecutionFactory,
4546
token?: CancellationToken,
4647
profileKind?: boolean | TestRunProfileKind,
47-
executionFactory?: IPythonExecutionFactory,
4848
debugLauncher?: ITestDebugLauncher,
4949
interpreter?: PythonEnvironment,
5050
): Promise<void> {
@@ -73,20 +73,18 @@ export class WorkspaceTestAdapter {
7373
}
7474
});
7575
const testCaseIds = Array.from(testCaseIdsSet);
76-
// ** execution factory only defined for new rewrite way
77-
if (executionFactory !== undefined) {
78-
await this.executionAdapter.runTests(
79-
this.workspaceUri,
80-
testCaseIds,
81-
profileKind,
82-
runInstance,
83-
executionFactory,
84-
debugLauncher,
85-
interpreter,
86-
);
87-
} else {
88-
await this.executionAdapter.runTests(this.workspaceUri, testCaseIds, profileKind);
76+
if (executionFactory === undefined) {
77+
throw new Error('Execution factory is required for test execution');
8978
}
79+
await this.executionAdapter.runTests(
80+
this.workspaceUri,
81+
testCaseIds,
82+
profileKind,
83+
runInstance,
84+
executionFactory,
85+
debugLauncher,
86+
interpreter,
87+
);
9088
deferred.resolve();
9189
} catch (ex) {
9290
// handle token and telemetry here

src/test/testing/testController/workspaceTestAdapter.unit.test.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ suite('Workspace test adapter', () => {
256256
let testControllerMock: typemoq.IMock<TestController>;
257257
let telemetryEvent: { eventName: EventName; properties: Record<string, unknown> }[] = [];
258258
let resultResolver: ResultResolver.PythonResultResolver;
259+
let execFactory: typemoq.IMock<IPythonExecutionFactory>;
259260

260261
// Stubbed test controller (see comment around L.40)
261262
let testController: TestController;
@@ -328,6 +329,7 @@ suite('Workspace test adapter', () => {
328329

329330
executionTestsStub = sandbox.stub(UnittestTestExecutionAdapter.prototype, 'runTests');
330331
sendTelemetryStub = sandbox.stub(Telemetry, 'sendTelemetryEvent').callsFake(mockSendTelemetryEvent);
332+
execFactory = typemoq.Mock.ofType<IPythonExecutionFactory>();
331333
runInstance = typemoq.Mock.ofType<TestRun>();
332334

333335
const testProvider = 'pytest';
@@ -384,7 +386,12 @@ suite('Workspace test adapter', () => {
384386
testControllerMock = typemoq.Mock.ofType<TestController>();
385387
testControllerMock.setup((t) => t.items).returns(() => testItemCollectionMock.object);
386388

387-
await workspaceTestAdapter.executeTests(testController, runInstance.object, [mockTestItem1, mockTestItem2]);
389+
await workspaceTestAdapter.executeTests(
390+
testController,
391+
runInstance.object,
392+
[mockTestItem1, mockTestItem2],
393+
execFactory.object,
394+
);
388395

389396
runInstance.verify((r) => r.started(typemoq.It.isAny()), typemoq.Times.exactly(2));
390397
});
@@ -400,7 +407,7 @@ suite('Workspace test adapter', () => {
400407
stubResultResolver,
401408
);
402409

403-
await workspaceTestAdapter.executeTests(testController, runInstance.object, []);
410+
await workspaceTestAdapter.executeTests(testController, runInstance.object, [], execFactory.object);
404411

405412
sinon.assert.calledOnce(executionTestsStub);
406413
});
@@ -427,8 +434,8 @@ suite('Workspace test adapter', () => {
427434
);
428435

429436
// Try running discovery twice
430-
const one = workspaceTestAdapter.executeTests(testController, runInstance.object, []);
431-
const two = workspaceTestAdapter.executeTests(testController, runInstance.object, []);
437+
const one = workspaceTestAdapter.executeTests(testController, runInstance.object, [], execFactory.object);
438+
const two = workspaceTestAdapter.executeTests(testController, runInstance.object, [], execFactory.object);
432439

433440
Promise.all([one, two]);
434441

@@ -467,7 +474,7 @@ suite('Workspace test adapter', () => {
467474
const buildErrorNodeOptionsStub = sinon.stub(util, 'buildErrorNodeOptions').returns(errorTestItemOptions);
468475
const testProvider = 'unittest';
469476

470-
await workspaceTestAdapter.executeTests(testController, runInstance.object, []);
477+
await workspaceTestAdapter.executeTests(testController, runInstance.object, [], execFactory.object);
471478

472479
sinon.assert.calledWithMatch(createErrorTestItemStub, sinon.match.any, sinon.match.any);
473480
sinon.assert.calledWithMatch(buildErrorNodeOptionsStub, Uri.parse('foo'), sinon.match.any, testProvider);
@@ -487,7 +494,7 @@ suite('Workspace test adapter', () => {
487494
stubResultResolver,
488495
);
489496

490-
await workspaceTestAdapter.executeTests(testController, runInstance.object, []);
497+
await workspaceTestAdapter.executeTests(testController, runInstance.object, [], execFactory.object);
491498

492499
sinon.assert.calledWith(sendTelemetryStub, EventName.UNITTEST_RUN_ALL_FAILED);
493500
assert.strictEqual(telemetryEvent.length, 1);

0 commit comments

Comments
 (0)