PY-58751 Unable to jump to location of "synthetic" test item

Merge-request: IJ-MR-174410
Merged-by: Egor Eliseev <Egor.Eliseev@jetbrains.com>

GitOrigin-RevId: 858bccafb9ae0343fafa5bac4cc0f88c0778898d
This commit is contained in:
Ilya Konstantinov
2025-09-08 13:19:40 +00:00
committed by intellij-monorepo-bot
parent e5535ffc3c
commit 2226dd547f
3 changed files with 32 additions and 15 deletions
+20 -9
View File
@@ -130,12 +130,20 @@ class NewTeamcityServiceMessages(_old_service_messages):
# tests with docstrings are reported in format "test.name (some test here)".
# text should be part of name, but not location.
possible_location = str(full_name)
loc = possible_location.find("(")
if loc > 0:
possible_location = possible_location[:loc].strip()
properties["locationHint"] = "python<{0}>://{1}".format(PROJECT_DIR,
possible_location)
path = properties.get('path')
if not path or path.endswith('.py'):
possible_location = str(full_name)
loc = possible_location.find("(")
if loc > 0:
possible_location = possible_location[:loc].strip()
properties["locationHint"] = "python<{0}>://{1}".format(PROJECT_DIR, possible_location)
else:
# For data-driven tests, we reference the test by file and line number.
location_hint = "file:/" + path
lineno = properties.get('lineno')
if lineno:
location_hint += ":{}".format(lineno)
properties["locationHint"] = location_hint
except KeyError:
# If message does not have name, then it is not test
# Simply pass it
@@ -205,13 +213,16 @@ class NewTeamcityServiceMessages(_old_service_messages):
self.testStarted(".".join(_TREE_MANAGER_HOLDER.manager.current_branch + [name]))
self._latest_subtest_result = subTestResult
def testStarted(self, testName, captureStandardOutput=None, flowId=None, is_suite=False, metainfo=None):
def testStarted(self, testName, captureStandardOutput=None, flowId=None, is_suite=False, metainfo=None, path=None, lineno=None):
test_name_as_list = _jb_utils.test_to_list(testName)
testName = ".".join(test_name_as_list)
def _write_start_message():
# testName, captureStandardOutput, flowId
args = {"name": testName, "captureStandardOutput": captureStandardOutput, "metainfo": metainfo}
if path is not None and lineno is not None:
args["path"] = path
args["lineno"] = str(lineno)
if is_suite:
self.message("testSuiteStarted", **args)
else:
@@ -220,7 +231,7 @@ class NewTeamcityServiceMessages(_old_service_messages):
commands = _TREE_MANAGER_HOLDER.manager.level_opened(test_name_as_list, _write_start_message)
if commands:
self.do_commands(commands)
self.testStarted(testName, captureStandardOutput, is_suite=is_suite, metainfo=metainfo)
self.testStarted(testName, captureStandardOutput, is_suite=is_suite, metainfo=metainfo, path=path, lineno=lineno)
def testFailed(self, testName, message='', details='', flowId=None, comparison_failure=None):
testName = ".".join(_jb_utils.test_to_list(testName))
@@ -343,7 +354,7 @@ def jb_patch_targets(targets, fs_glue, old_python_glue, new_python_glue, fs_to_p
def jb_patch_separator(targets, fs_glue, python_glue, fs_to_python_glue):
"""
Converts python target if format "/path/foo.py::parts.to.python" provided by Java to
Converts python target if format "/path/foo.py::parts.to.python" provided by Java to
python-specific format
:param targets: list of dot-separated targets
+2 -2
View File
@@ -116,12 +116,12 @@ class TeamcityServiceMessages(object):
import teamcity.context_managers as cm
return cm.testSuite(self, name=name)
def testStarted(self, testName, captureStandardOutput=None, flowId=None, metainfo=None):
def testStarted(self, testName, captureStandardOutput=None, flowId=None, metainfo=None, **properties):
"""
:param metainfo: Used to pass any payload from test runner to Intellij. See IDEA-176950
"""
self.message('testStarted', name=testName, captureStandardOutput=captureStandardOutput, flowId=flowId, metainfo=metainfo)
self.message('testStarted', name=testName, captureStandardOutput=captureStandardOutput, flowId=flowId, metainfo=metainfo, **properties)
def testFinished(self, testName, testDuration=None, flowId=None):
if testDuration is not None:
@@ -94,6 +94,7 @@ class EchoTeamCityMessages(object):
output_handler = TeamCityMessagesPrinter(context_manager=context_manager)
self.teamcity = TeamcityServiceMessages(output_handler=output_handler)
self.test_start_reported_mark = set()
self.rootdir = None
self.current_test_item = None
self.max_reported_output_size = 1 * 1024 * 1024
@@ -178,28 +179,33 @@ class EchoTeamCityMessages(object):
self.report_test_finished(test_id)
def pytest_collection_finish(self, session):
if hasattr(session.config, 'rootpath'): # pytest>=6
self.rootdir = str(session.config.rootpath)
else:
self.rootdir = str(session.config.rootdir)
self.teamcity.testCount(len(session.items))
def pytest_runtest_logstart(self, nodeid, location):
# test name fetched from location passed as metainfo to PyCharm
# it will be used to run specific test
# See IDEA-176950, PY-31836
test_name = location[2]
path, lineno, test_name = location
if test_name:
test_name = str(test_name).split(".")[-1]
self.ensure_test_start_reported(self.format_test_id(nodeid, location), test_name)
path = os.path.join(self.rootdir, path)
self.ensure_test_start_reported(self.format_test_id(nodeid, location), test_name, path=path, lineno=lineno + 1)
def pytest_runtest_protocol(self, item):
self.current_test_item = item
return None # continue to next hook
def ensure_test_start_reported(self, test_id, metainfo=None):
def ensure_test_start_reported(self, test_id, metainfo=None, path=None, lineno=None):
if test_id not in self.test_start_reported_mark:
if self.output_capture_enabled:
capture_standard_output = "false"
else:
capture_standard_output = "true"
self.teamcity.testStarted(test_id, flowId=test_id, captureStandardOutput=capture_standard_output, metainfo=metainfo)
self.teamcity.testStarted(test_id, flowId=test_id, captureStandardOutput=capture_standard_output, metainfo=metainfo, path=path, lineno=lineno)
self.test_start_reported_mark.add(test_id)
def report_has_output(self, report):