From 8d638c7b93a8da583b9ca41d28b8312dc6af9d4a Mon Sep 17 00:00:00 2001 From: Darren Fuller Date: Fri, 1 Jul 2022 22:12:59 +0100 Subject: [PATCH 1/4] update unittest discovery to work with user defined top-level-directory --- pythonFiles/testing_tools/unittest_discovery.py | 5 +++-- .../testing/testController/unittest/arguments.ts | 12 ++++++++++++ .../testController/unittest/unittestController.ts | 5 +++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/pythonFiles/testing_tools/unittest_discovery.py b/pythonFiles/testing_tools/unittest_discovery.py index d13ea1c10dd9..4c175a66efee 100644 --- a/pythonFiles/testing_tools/unittest_discovery.py +++ b/pythonFiles/testing_tools/unittest_discovery.py @@ -1,11 +1,12 @@ -import unittest import inspect import os import sys import traceback +import unittest start_dir = sys.argv[1] pattern = sys.argv[2] +top_level_dir = sys.argv[3] sys.path.insert(0, os.getcwd()) @@ -38,7 +39,7 @@ def generate_test_cases(suite): try: loader = unittest.TestLoader() - suite = loader.discover(start_dir, pattern=pattern) + suite = loader.discover(start_dir, pattern=pattern, top_level_dir=top_level_dir) print("start") # Don't remove this line loader_errors = [] diff --git a/src/client/testing/testController/unittest/arguments.ts b/src/client/testing/testController/unittest/arguments.ts index 52ae484a87c2..e3d4a575bb68 100644 --- a/src/client/testing/testController/unittest/arguments.ts +++ b/src/client/testing/testController/unittest/arguments.ts @@ -73,6 +73,18 @@ export function unittestGetTestPattern(args: string[]): string { return 'test*.py'; } +export function unittestGetTopLevelDirectory(args: string[]): string { + const shortValue = getOptionValues(args, '-t'); + if (shortValue.length === 1) { + return shortValue[0]; + } + const longValue = getOptionValues(args, '--top-level-directory'); + if (longValue.length === 1) { + return longValue[0]; + } + return unittestGetTestFolders(args)[0]; +} + export function getTestRunArgs(args: string[]): string[] { const startTestDiscoveryDirectory = unittestGetTestFolders(args)[0]; const pattern = unittestGetTestPattern(args); diff --git a/src/client/testing/testController/unittest/unittestController.ts b/src/client/testing/testController/unittest/unittestController.ts index 2fb4cb91c539..62fe6cf6fc75 100644 --- a/src/client/testing/testController/unittest/unittestController.ts +++ b/src/client/testing/testController/unittest/unittestController.ts @@ -19,7 +19,7 @@ import { RawTestParent, TestData, } from '../common/types'; -import { unittestGetTestFolders, unittestGetTestPattern } from './arguments'; +import { unittestGetTestFolders, unittestGetTestPattern, unittestGetTopLevelDirectory } from './arguments'; import { createErrorTestItem, createWorkspaceRootTestItem, @@ -130,6 +130,7 @@ export class UnittestController implements ITestFrameworkController { const startDir = unittestGetTestFolders(options.args)[0]; const pattern = unittestGetTestPattern(options.args); + const topLevelDir = unittestGetTopLevelDirectory(options.args); let testDir = startDir; if (path.isAbsolute(startDir)) { const relative = path.relative(options.cwd, startDir); @@ -139,7 +140,7 @@ export class UnittestController implements ITestFrameworkController { const runOptions: Options = { // unittest needs to load modules in the workspace // isolating it breaks unittest discovery - args: unittestDiscovery([startDir, pattern]), + args: unittestDiscovery([startDir, pattern, topLevelDir]), cwd: options.cwd, workspaceFolder: options.workspaceFolder, token: options.token, From 8d9e4baabe4e7d100e1800d317fbeca9255c76a8 Mon Sep 17 00:00:00 2001 From: Darren Fuller Date: Sat, 2 Jul 2022 09:51:47 +0100 Subject: [PATCH 2/4] change to make top-level-dir optional --- pythonFiles/testing_tools/unittest_discovery.py | 2 +- src/client/testing/testController/unittest/arguments.ts | 4 ++-- .../testing/testController/unittest/unittestController.ts | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pythonFiles/testing_tools/unittest_discovery.py b/pythonFiles/testing_tools/unittest_discovery.py index 4c175a66efee..2988092c387c 100644 --- a/pythonFiles/testing_tools/unittest_discovery.py +++ b/pythonFiles/testing_tools/unittest_discovery.py @@ -6,7 +6,7 @@ start_dir = sys.argv[1] pattern = sys.argv[2] -top_level_dir = sys.argv[3] +top_level_dir = sys.argv[3] if len(sys.argv) >= 4 else None sys.path.insert(0, os.getcwd()) diff --git a/src/client/testing/testController/unittest/arguments.ts b/src/client/testing/testController/unittest/arguments.ts index e3d4a575bb68..105f8e56880c 100644 --- a/src/client/testing/testController/unittest/arguments.ts +++ b/src/client/testing/testController/unittest/arguments.ts @@ -73,7 +73,7 @@ export function unittestGetTestPattern(args: string[]): string { return 'test*.py'; } -export function unittestGetTopLevelDirectory(args: string[]): string { +export function unittestGetTopLevelDirectory(args: string[]): string | null { const shortValue = getOptionValues(args, '-t'); if (shortValue.length === 1) { return shortValue[0]; @@ -82,7 +82,7 @@ export function unittestGetTopLevelDirectory(args: string[]): string { if (longValue.length === 1) { return longValue[0]; } - return unittestGetTestFolders(args)[0]; + return null; } export function getTestRunArgs(args: string[]): string[] { diff --git a/src/client/testing/testController/unittest/unittestController.ts b/src/client/testing/testController/unittest/unittestController.ts index 62fe6cf6fc75..ee79103c4e3e 100644 --- a/src/client/testing/testController/unittest/unittestController.ts +++ b/src/client/testing/testController/unittest/unittestController.ts @@ -137,10 +137,13 @@ export class UnittestController implements ITestFrameworkController { testDir = relative.length > 0 ? relative : '.'; } + const runOptionsArgs: string[] = + topLevelDir == null ? [startDir, pattern] : [startDir, pattern, topLevelDir]; + const runOptions: Options = { // unittest needs to load modules in the workspace // isolating it breaks unittest discovery - args: unittestDiscovery([startDir, pattern, topLevelDir]), + args: unittestDiscovery(runOptionsArgs), cwd: options.cwd, workspaceFolder: options.workspaceFolder, token: options.token, From 98fe44f4b15233c95a01468fbd6d1a1368f994fb Mon Sep 17 00:00:00 2001 From: Darren Fuller Date: Sat, 2 Jul 2022 10:51:23 +0100 Subject: [PATCH 3/4] add top-level-dir to unittest run args --- src/client/testing/testController/unittest/arguments.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/client/testing/testController/unittest/arguments.ts b/src/client/testing/testController/unittest/arguments.ts index 105f8e56880c..caff87999f6e 100644 --- a/src/client/testing/testController/unittest/arguments.ts +++ b/src/client/testing/testController/unittest/arguments.ts @@ -88,10 +88,14 @@ export function unittestGetTopLevelDirectory(args: string[]): string | null { export function getTestRunArgs(args: string[]): string[] { const startTestDiscoveryDirectory = unittestGetTestFolders(args)[0]; const pattern = unittestGetTestPattern(args); + const topLevelDir = unittestGetTopLevelDirectory(args); const failFast = args.some((arg) => arg.trim() === '-f' || arg.trim() === '--failfast'); const verbosity = args.some((arg) => arg.trim().indexOf('-v') === 0) ? 2 : 1; const testArgs = [`--us=${startTestDiscoveryDirectory}`, `--up=${pattern}`, `--uvInt=${verbosity}`]; + if (topLevelDir) { + testArgs.push(`--ut=${topLevelDir}`); + } if (failFast) { testArgs.push('--uf'); } From 82ff72b1d5c686be67ac9c1b51636d90bce3109d Mon Sep 17 00:00:00 2001 From: Darren Fuller Date: Sat, 2 Jul 2022 10:58:06 +0100 Subject: [PATCH 4/4] update test discovery to use top-level-directory --- pythonFiles/visualstudio_py_testlauncher.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pythonFiles/visualstudio_py_testlauncher.py b/pythonFiles/visualstudio_py_testlauncher.py index 7f80dfa3ba88..0b0ef3242f65 100644 --- a/pythonFiles/visualstudio_py_testlauncher.py +++ b/pythonFiles/visualstudio_py_testlauncher.py @@ -17,14 +17,13 @@ __author__ = "Microsoft Corporation " __version__ = "3.0.0.0" -import os -import sys import json -import unittest +import os +import signal import socket +import sys import traceback -from types import CodeType, FunctionType -import signal +import unittest try: import thread @@ -295,8 +294,8 @@ def main(): if opts.mixed_mode: # For mixed-mode attach, there's no ptvsd and hence no wait_for_attach(), # so we have to use Win32 API in a loop to do the same thing. + from ctypes import c_char, windll from time import sleep - from ctypes import windll, c_char while True: if windll.kernel32.IsDebuggerPresent() != 0: @@ -334,7 +333,9 @@ def main(): # Easier approach is find the test suite and use that for running loader = unittest.TestLoader() # opts.us will be passed in - suites = loader.discover(opts.us, pattern=os.path.basename(opts.testFile)) + suites = loader.discover( + opts.us, pattern=os.path.basename(opts.testFile), top_level_dir=opts.ut + ) suite = None tests = None if opts.tests is None: