Skip to content

Commit

Permalink
fix: handle cases where pytest itself fails (#70)
Browse files Browse the repository at this point in the history
* Check if traceback location is not `None`

* Check if exception repr object is not null before retrieving message and lineno

* Remove `__future__.print_function` import

* Add test

* Match line using regex
  • Loading branch information
edgarrmondragon authored Apr 20, 2023
1 parent b94d206 commit 0bf8cc7
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
22 changes: 22 additions & 0 deletions plugin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,28 @@ def test_success():
no_fnmatch_line(result, "::error file=test_annotation_succeed_no_output.py")


def test_annotation_pytest_error(testdir):
testdir.makepyfile(
"""
import pytest
pytest_plugins = 'pytest_github_actions_annotate_failures'
@pytest.fixture
def fixture():
return 1
def test_error():
assert fixture() == 1
"""
)
testdir.monkeypatch.setenv("GITHUB_ACTIONS", "true")
result = testdir.runpytest_subprocess()

result.stderr.re_match_lines(
[r"::error file=test_annotation_pytest_error\.py,line=8::test_error.*",]
)


def test_annotation_fail(testdir):
testdir.makepyfile(
"""
Expand Down
28 changes: 19 additions & 9 deletions pytest_github_actions_annotate_failures/plugin.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import print_function

from __future__ import annotations

import os
import sys
from collections import OrderedDict
from typing import TYPE_CHECKING

from _pytest._code.code import ExceptionRepr

import pytest

if TYPE_CHECKING:
from _pytest.nodes import Item
from _pytest.reports import CollectReport


# Reference:
# https://docs.pytest.org/en/latest/writing_plugins.html#hookwrapper-executing-around-other-hooks
# https://docs.pytest.org/en/latest/writing_plugins.html#hook-function-ordering-call-example
Expand All @@ -17,10 +26,10 @@


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
def pytest_runtest_makereport(item: Item, call):
# execute all other hooks to obtain the report object
outcome = yield
report = outcome.get_result()
report: CollectReport = outcome.get_result()

# enable only in a workflow of GitHub Actions
# ref: https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
Expand Down Expand Up @@ -57,13 +66,14 @@ def pytest_runtest_makereport(item, call):
longrepr = report.head_line or item.name

# get the error message and line number from the actual error
if hasattr(report.longrepr, "reprcrash"):
longrepr += "\n\n" + report.longrepr.reprcrash.message
traceback_entries = report.longrepr.reprtraceback.reprentries
if len(traceback_entries) > 1:
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:
# Handle third-party exceptions
lineno = traceback_entries[0].reprfileloc.lineno
else:
lineno = tb_entries[0].reprfileloc.lineno
elif report.longrepr.reprcrash is not None:
lineno = report.longrepr.reprcrash.lineno
elif isinstance(report.longrepr, tuple):
_, lineno, message = report.longrepr
Expand Down

0 comments on commit 0bf8cc7

Please sign in to comment.