Skip to content

Commit

Permalink
Support Pytest 7.4+
Browse files Browse the repository at this point in the history
Co-authored-by: Henry Schreiner <[email protected]>
  • Loading branch information
edgarrmondragon and henryiii committed Jan 17, 2025
1 parent e4336fb commit 0ed0695
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 36 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ jobs:
PYTEST_MAJOR_VERSION: 7
PYTEST_PLUGINS: pytest_github_actions_annotate_failures

- name: Run tests with PyTest 8
run: tox
env:
PYTEST_MAJOR_VERSION: 8
PYTEST_PLUGINS: pytest_github_actions_annotate_failures

post-test:
name: All tests passed
if: always()
Expand Down
2 changes: 1 addition & 1 deletion plugin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def test_fail():
result = testdir.runpytest_subprocess("--rootdir=foo")
result.stderr.fnmatch_lines(
[
"::error file=test_annotation_fail_cwd.py,line=5::test_fail*assert 0*",
"::error file=test_annotation_fail_cwd0/test_annotation_fail_cwd.py,line=5::test_fail*assert 0*",
]
)

Expand Down
74 changes: 40 additions & 34 deletions pytest_github_actions_annotate_failures/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import TYPE_CHECKING

import pytest
from _pytest._code.code import ExceptionRepr
from _pytest._code.code import ExceptionRepr, ReprEntry
from packaging import version

if TYPE_CHECKING:
Expand Down Expand Up @@ -38,59 +38,65 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001
return

if report.when == "call" and report.failed:
# collect information to be annotated
filesystempath, lineno, _ = report.location

runpath = os.environ.get("PYTEST_RUN_PATH")
if runpath:
filesystempath = os.path.join(runpath, filesystempath)

# try to convert to absolute path in GitHub Actions
workspace = os.environ.get("GITHUB_WORKSPACE")
if workspace:
full_path = os.path.abspath(filesystempath)
try:
rel_path = os.path.relpath(full_path, workspace)
except ValueError:
# os.path.relpath() will raise ValueError on Windows
# when full_path and workspace have different mount points.
# https://github.com/utgwkk/pytest-github-actions-annotate-failures/issues/20
rel_path = filesystempath
if not rel_path.startswith(".."):
filesystempath = rel_path

if lineno is not None:
# 0-index to 1-index
lineno += 1

# get the name of the current failed test, with parametrize info
longrepr = report.head_line or item.name

# get the error message and line number from the actual error
if isinstance(report.longrepr, ExceptionRepr):
if report.longrepr.reprcrash is not None:
longrepr += "\n\n" + report.longrepr.reprcrash.message
tb_entries = report.longrepr.reprtraceback.reprentries
if len(tb_entries) > 1 and tb_entries[0].reprfileloc is not None:
if tb_entries:
entry = tb_entries[0]
# Handle third-party exceptions
lineno = tb_entries[0].reprfileloc.lineno
if isinstance(entry, ReprEntry) and entry.reprfileloc is not None:
lineno = entry.reprfileloc.lineno
filesystempath = entry.reprfileloc.path

elif report.longrepr.reprcrash is not None:
lineno = report.longrepr.reprcrash.lineno
elif isinstance(report.longrepr, tuple):
_, lineno, message = report.longrepr
filesystempath, lineno, message = report.longrepr
longrepr += "\n\n" + message
elif isinstance(report.longrepr, str):
longrepr += "\n\n" + report.longrepr

workflow_command = _build_workflow_command(
"error",
filesystempath,
compute_path(filesystempath),
lineno,
message=longrepr,
)
print(workflow_command, file=sys.stderr)


def compute_path(filesystempath: str) -> str:
"""Extract and process location information from the report."""
runpath = os.environ.get("PYTEST_RUN_PATH")
if runpath:
filesystempath = os.path.join(runpath, filesystempath)

# try to convert to absolute path in GitHub Actions
workspace = os.environ.get("GITHUB_WORKSPACE")
if workspace:
full_path = os.path.abspath(filesystempath)
try:
rel_path = os.path.relpath(full_path, workspace)
except ValueError:
# os.path.relpath() will raise ValueError on Windows
# when full_path and workspace have different mount points.
rel_path = filesystempath
if not rel_path.startswith(".."):
filesystempath = rel_path

return filesystempath


class _AnnotateWarnings:
def pytest_warning_recorded(self, warning_message, when, nodeid, location): # noqa: ARG002
# enable only in a workflow of GitHub Actions
Expand Down Expand Up @@ -139,14 +145,14 @@ def pytest_configure(config):


def _build_workflow_command(
command_name,
file,
line,
end_line=None,
column=None,
end_column=None,
title=None,
message=None,
command_name: str,
file: str,
line: int,
end_line: int | None = None,
column: int | None = None,
end_column: int | None = None,
title: str | None = None,
message: str | None = None,
):
"""Build a command to annotate a workflow."""
result = f"::{command_name} "
Expand All @@ -168,5 +174,5 @@ def _build_workflow_command(
return result


def _escape(s):
def _escape(s: str) -> str:
return s.replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ PYTEST_MAJOR_VERSION =
extras = test
deps =
pytest6: pytest>=6.0.0,<7.0.0
pytest7: pytest>=7.0.0,<7.4.0
pytest7: pytest>=7.0.0,<8.0.0
pytest8: pytest>=8.0.0,<9.0.0

commands = {envpython} -m pytest {posargs}

0 comments on commit 0ed0695

Please sign in to comment.