in Python/Product/TestAdapter/visualstudio_py_testlauncher.py [0:0]
def main():
import os
from optparse import OptionParser
global _channel
parser = OptionParser(prog = 'visualstudio_py_testlauncher', usage = 'Usage: %prog [<option>] <test names>... ')
parser.add_option('-s', '--secret', metavar='<secret>', help='restrict server to only allow clients that specify <secret> when connecting (legacy debugger only)')
parser.add_option('-p', '--port', type='int', metavar='<port>', help='listen for debugger connections on <port>')
parser.add_option('-x', '--mixed-mode', action='store_true', help='wait for mixed-mode debugger to attach')
parser.add_option('-t', '--test', type='str', dest='tests', action='append', help='specifies a test to run')
parser.add_option('-c', '--coverage', type='str', help='enable code coverage and specify filename')
parser.add_option('-r', '--result-port', type='int', help='connect to port on localhost and send test results')
parser.add_option('--test-list', metavar='<file>', type='str', help='read tests from this file')
parser.add_option('--dry-run', action='store_true', help='prints a list of tests without executing them')
(opts, _) = parser.parse_args()
sys.path.insert(1, os.getcwd())
if opts.result_port:
_channel = _IpcChannel(socket.create_connection(('127.0.0.1', opts.result_port)))
sys.stdout = _TestOutput(sys.stdout, is_stdout = True)
sys.stderr = _TestOutput(sys.stderr, is_stdout = False)
if opts.secret and opts.port:
from ptvsd.debugger import DONT_DEBUG, DEBUG_ENTRYPOINTS, get_code
from ptvsd import DEFAULT_PORT, enable_attach, wait_for_attach
DONT_DEBUG.append(os.path.normcase(__file__))
DEBUG_ENTRYPOINTS.add(get_code(main))
enable_attach(opts.secret, ('127.0.0.1', getattr(opts, 'port', DEFAULT_PORT)), redirect_output = True)
wait_for_attach()
elif opts.port:
import debugpy
debugpy.listen(('127.0.0.1', getattr(opts, 'port', 5678)))
debugpy.wait_for_client()
elif 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 time import sleep
from ctypes import windll, c_char
while True:
if windll.kernel32.IsDebuggerPresent() != 0:
break
sleep(0.1)
try:
debugger_helper = windll['Microsoft.PythonTools.Debugger.Helper.x86.dll']
except WindowsError:
debugger_helper = windll['Microsoft.PythonTools.Debugger.Helper.x64.dll']
isTracing = c_char.in_dll(debugger_helper, "isTracing")
while True:
if isTracing.value != 0:
break
sleep(0.1)
all_tests = list(opts.tests or [])
if opts.test_list:
with io.open(opts.test_list, 'r', encoding='utf-8') as test_list:
all_tests.extend(t.strip() for t in test_list)
if opts.dry_run:
if _channel:
for test in all_tests:
print(test)
_channel.send_event(
name='start',
test = test
)
_channel.send_event(
name='result',
outcome='passed',
test = test
)
else:
for test in all_tests:
print(test)
sys.exit(0)
cov = None
try:
if opts.coverage:
try:
import coverage
cov = coverage.coverage(opts.coverage)
cov.load()
cov.start()
except:
pass
tests = []
for test in all_tests:
if not test:
continue
try:
for loaded_test in unittest.defaultTestLoader.loadTestsFromName(test):
# Starting with Python 3.5, rather than letting any import error
# exception propagate out of loadTestsFromName, unittest catches it and
# creates instance(s) of unittest.loader._FailedTest.
# Those have an unexpected test.id(), ex: 'unittest.loader._FailedTest.test1'
# Store the test id passed in as an additional attribute and
# VsTestResult will use that instead of test.id().
loaded_test.test_id = test
tests.append(loaded_test)
except Exception:
trace = sys.exc_info()
traceback.print_exception(*trace)
tb = _get_traceback(trace)
message = str(trace[1])
if _channel is not None:
_channel.send_event(
name='start',
test = test
)
_channel.send_event(
name='result',
outcome='failed',
traceback = tb,
message = message,
test = test
)
if _IS_OLD_UNITTEST:
def _makeResult(self):
return VsTestResult(self.stream, self.descriptions, self.verbosity)
unittest.TextTestRunner._makeResult = _makeResult
runner = unittest.TextTestRunner(verbosity=0)
else:
runner = unittest.TextTestRunner(verbosity=0, resultclass=VsTestResult)
result = runner.run(unittest.defaultTestLoader.suiteClass(tests))
sys.exit(not result.wasSuccessful())
finally:
if cov is not None:
cov.stop()
cov.save()
cov.xml_report(outfile = opts.coverage + '.xml', omit=__file__)
if _channel is not None:
_channel.send_event(
name='done'
)
_channel.close()