Skip to content

Commit 4109228

Browse files
authored
fix debugging with new pytest run script (#21299)
fix debugging for run_pytest_script.py setup
1 parent b916981 commit 4109228

File tree

4 files changed

+29
-18
lines changed

4 files changed

+29
-18
lines changed

src/client/common/process/internal/scripts/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ export function testlauncher(testArgs: string[]): string[] {
110110
return [script, ...testArgs];
111111
}
112112

113+
// run_pytest_script.py
114+
export function pytestlauncher(testArgs: string[]): string[] {
115+
const script = path.join(SCRIPTS_DIR, 'vscode_pytest', 'run_pytest_script.py');
116+
// There is no output to parse, so we do not return a function.
117+
return [script, ...testArgs];
118+
}
119+
113120
// visualstudio_py_testlauncher.py
114121

115122
// eslint-disable-next-line camelcase

src/client/testing/common/debugLauncher.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,7 @@ export class DebugLauncher implements ITestDebugLauncher {
178178
const args = script(testArgs);
179179
const [program] = args;
180180
configArgs.program = program;
181-
// if the test provider is pytest, then use the pytest module instead of using a program
182-
const rewriteTestingEnabled = process.env.ENABLE_PYTHON_TESTING_REWRITE;
183-
if (options.testProvider === 'pytest' && rewriteTestingEnabled) {
184-
configArgs.module = 'pytest';
185-
configArgs.program = undefined;
186-
}
181+
187182
configArgs.args = args.slice(1);
188183
// We leave configArgs.request as "test" so it will be sent in telemetry.
189184

@@ -204,12 +199,16 @@ export class DebugLauncher implements ITestDebugLauncher {
204199
throw Error(`Invalid debug config "${debugConfig.name}"`);
205200
}
206201
launchArgs.request = 'launch';
202+
203+
// If we are in the pytest rewrite then we must send additional environment variables.
204+
const rewriteTestingEnabled = process.env.ENABLE_PYTHON_TESTING_REWRITE;
207205
if (options.testProvider === 'pytest' && rewriteTestingEnabled) {
208206
if (options.pytestPort && options.pytestUUID) {
209207
launchArgs.env = {
210208
...launchArgs.env,
211209
TEST_PORT: options.pytestPort,
212210
TEST_UUID: options.pytestUUID,
211+
RUN_TEST_IDS_PORT: options.pytestRunTestIdsPort,
213212
};
214213
} else {
215214
throw Error(
@@ -238,7 +237,7 @@ export class DebugLauncher implements ITestDebugLauncher {
238237
}
239238
case 'pytest': {
240239
if (rewriteTestingEnabled) {
241-
return (testArgs: string[]) => testArgs;
240+
return internalScripts.pytestlauncher; // this is the new way to run pytest execution, debugger
242241
}
243242
return internalScripts.testlauncher; // old way pytest execution, debugger
244243
}

src/client/testing/common/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type LaunchOptions = {
2727
outChannel?: OutputChannel;
2828
pytestPort?: string;
2929
pytestUUID?: string;
30+
pytestRunTestIdsPort?: string;
3031
};
3132

3233
export type ParserOptions = TestDiscoveryOptions;

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as path from 'path';
66
import * as net from 'net';
77
import { IConfigurationService, ITestOutputChannel } from '../../../common/types';
88
import { createDeferred, Deferred } from '../../../common/utils/async';
9-
import { traceLog, traceVerbose } from '../../../logging';
9+
import { traceError, traceLog, traceVerbose } from '../../../logging';
1010
import { DataReceivedEvent, ExecutionTestPayload, ITestExecutionAdapter, ITestServer } from '../common/types';
1111
import {
1212
ExecutionFactoryCreateWithEnvironmentOptions,
@@ -112,18 +112,16 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
112112
testArgs.splice(0, 0, '--rootdir', uri.fsPath);
113113
}
114114

115-
// why is this needed?
116115
if (debugBool && !testArgs.some((a) => a.startsWith('--capture') || a === '-s')) {
117116
testArgs.push('--capture', 'no');
118117
}
119-
const pluginArgs = ['-p', 'vscode_pytest'].concat(testArgs).concat(testIds);
120-
const scriptPath = path.join(fullPluginPath, 'vscode_pytest', 'run_pytest_script.py');
121-
const runArgs = [scriptPath, ...testArgs];
122118

119+
// create payload with testIds to send to run pytest script
123120
const testData = JSON.stringify(testIds);
124121
const headers = [`Content-Length: ${Buffer.byteLength(testData)}`, 'Content-Type: application/json'];
125122
const payload = `${headers.join('\r\n')}\r\n\r\n${testData}`;
126123

124+
let pytestRunTestIdsPort: string | undefined;
127125
const startServer = (): Promise<number> =>
128126
new Promise((resolve, reject) => {
129127
const server = net.createServer((socket: net.Socket) => {
@@ -151,34 +149,40 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
151149
await startServer()
152150
.then((assignedPort) => {
153151
traceLog(`Server started and listening on port ${assignedPort}`);
152+
pytestRunTestIdsPort = assignedPort.toString();
154153
if (spawnOptions.extraVariables)
155-
spawnOptions.extraVariables.RUN_TEST_IDS_PORT = assignedPort.toString();
154+
spawnOptions.extraVariables.RUN_TEST_IDS_PORT = pytestRunTestIdsPort;
156155
})
157156
.catch((error) => {
158-
console.error('Error starting server:', error);
157+
traceError('Error starting server:', error);
159158
});
160159

161160
if (debugBool) {
162161
const pytestPort = this.testServer.getPort().toString();
163162
const pytestUUID = uuid.toString();
164163
const launchOptions: LaunchOptions = {
165164
cwd: uri.fsPath,
166-
args: pluginArgs,
165+
args: testArgs,
167166
token: spawnOptions.token,
168167
testProvider: PYTEST_PROVIDER,
169168
pytestPort,
170169
pytestUUID,
170+
pytestRunTestIdsPort,
171171
};
172-
console.debug(`Running debug test with arguments: ${pluginArgs.join(' ')}\r\n`);
172+
traceVerbose(`Running debug test with arguments: ${testArgs.join(' ')}\r\n`);
173173
await debugLauncher!.launchDebugger(launchOptions);
174174
} else {
175+
// combine path to run script with run args
176+
const scriptPath = path.join(fullPluginPath, 'vscode_pytest', 'run_pytest_script.py');
177+
const runArgs = [scriptPath, ...testArgs];
178+
175179
await execService?.exec(runArgs, spawnOptions).catch((ex) => {
176-
console.debug(`Error while running tests: ${testIds}\r\n${ex}\r\n\r\n`);
180+
traceError(`Error while running tests: ${testIds}\r\n${ex}\r\n\r\n`);
177181
return Promise.reject(ex);
178182
});
179183
}
180184
} catch (ex) {
181-
console.debug(`Error while running tests: ${testIds}\r\n${ex}\r\n\r\n`);
185+
traceVerbose(`Error while running tests: ${testIds}\r\n${ex}\r\n\r\n`);
182186
return Promise.reject(ex);
183187
}
184188

0 commit comments

Comments
 (0)