Closed OddBloke closed 1 year ago
The below does set the tbstyle
to long
unconditionally, overriding a pytest.ini
setting, and ensuring I get line-level diagnostics. This does mean, however, that the output displayed by neotest-python
will be different to the CLI output if users do have a --tb
setting, which is less than ideal.
diff --git a/neotest_python/pytest.py b/neotest_python/pytest.py
index a6010d7..741edfa 100644
--- a/neotest_python/pytest.py
+++ b/neotest_python/pytest.py
@@ -81,6 +81,7 @@ class NeotestResultCollector:
self.results[pos_id] = result
def pytest_cmdline_main(self, config: "Config"):
+ config.option.tbstyle = "long"
self.pytest_config = config
def pytest_runtest_logreport(self, report: "TestReport"):
An alternative approach, which adds code to handle native tracebacks:
--- a/neotest_python/pytest.py
+++ b/neotest_python/pytest.py
@@ -1,3 +1,4 @@
+import re
from io import StringIO
from pathlib import Path
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Union
@@ -9,6 +10,18 @@ if TYPE_CHECKING:
from _pytest.reports import TestReport
+def _lineno_of_uppermost_frame_in_file(path: str, lines: List[str]) -> Optional[int]:
+ # lines should be ReprEntry.lines or NativeReprEntry.lines, this will find
+ # the top frame in the traceback within the given path and return its line
+ error_line = None
+ for line in reversed(lines):
+ # File "/path/to/file.py", line 2
+ match = re.search(r'File "(?P<path>.*)", line (?P<line>\d+)', line)
+ if match is not None and match.group("path") == path:
+ error_line = int(match.group("line")) - 1
+ return error_line
+
+
class PytestNeotestAdapter(NeotestAdapter):
def run(
self,
@@ -116,6 +129,11 @@ class NeotestResultCollector:
and repr.reprfileloc.path == file_path
):
error_line = repr.reprfileloc.lineno - 1
+ if error_line is None:
+ # Fall back to parsing traceback lines
+ error_line = _lineno_of_uppermost_frame_in_file(
+ abs_path, repr.lines
+ )
errors.append({"message": error_message, "line": error_line})
else:
# TODO: Figure out how these are returned and how to represent
From discussion in #27: this is because pytest returns a different internal representation of the traceback based on the
--tb
setting.