Repository: okken/pytest-check (language: python)

Issue:
[v2.2.3] ExceptionRepr creation is not compatible with pytest < 7.3.
Hi,

It seems that pytest-check relies on latest pytest version, but in our environment we have frozen pytest version 7.2.2.
Line introduced in 2.2.3 
`reprtraceback = ExceptionRepr(reprcrash, excinfo)`
is not possible to be executed in pytest < 7.3 as ExceptionRepr was changed there
[ExceptionRepr 7.3 changes](https://github.com/pytest-dev/pytest/commit/310b67b2271cb05f575054c1cdd2ece2412c89a2#diff-ac2099a172465905236568f8c175328fb75ebc1b80ce39f4799e61373d355418L999)

7.2.2
```
>>> from _pytest._code.code import ExceptionRepr
>>> ExceptionRepr(None, None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ExceptionRepr.__init__() takes 1 positional argument but 3 were given
```

7.3.0+
```
>>> from _pytest._code.code import ExceptionRepr
>>> ExceptionRepr(None, None)
ExceptionRepr(reprtraceback=None, reprcrash=None, sections=[])
```

Could you please take a look? Thank you!


Discussion / hints:

Fix patch:
diff --git a/changelog.md b/changelog.md
index b5166da..b0d7a90 100644
--- a/changelog.md
+++ b/changelog.md
@@ -20,6 +20,15 @@ All notable changes to this project  be documented in this file.
 
 -->
 
+## [2.2.4] - 2024-Jan-*
+
+- fix [153](https://github.com/okken/pytest-check/issues/153)
+  - Summaries from 2.2.3 are cool, but don't work for pytest < 7.3
+  - Remove them for earlier pytest
+  - Add tox test run for pytest 7.0.0
+  - Change dependencies to require 7.0.0 pytest
+
+
 ## [2.2.3] - 2023-Dec-31
 
 - Check failure info now shows up in summaries.
diff --git a/pyproject.toml b/pyproject.toml
index 8bd402a..f16c55d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,13 +4,13 @@ authors = [{name = "Brian Okken"}]
 readme = "README.md"
 license = {file = "LICENSE.txt"}
 description="A pytest plugin that allows multiple failures per test."
-version = "2.2.3"
+version = "2.2.4"
 requires-python = ">=3.7"
 classifiers = [
     "License :: OSI Approved :: MIT License",
     "Framework :: Pytest" ,
 ]
-dependencies = ["pytest"]
+dependencies = ["pytest>=7.0.0"]
 
 [project.urls]
 Home = "https://github.com/okken/pytest-check"
diff --git a/tox.ini b/tox.ini
index 8018dae..65fa20e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py37, py38, py39, py310, py311, py312, coverage, lint
+envlist = py37, py38, py39, py310, py311, py312, pytest_earliest, coverage, lint
 
 skip_missing_interpreters = true
 
@@ -17,6 +17,12 @@ commands =
     coverage report --fail-under=100 --show-missing
 description = Run pytest, with coverage
 
+[testenv:pytest_earliest]
+deps = pytest==7.0.0
+basepython = python3.11
+commands = pytest {posargs}
+description = Run earliest supported pytest
+
 [testenv:lint]
 skip_install = true
 deps = ruff
@@ -25,10 +31,10 @@ commands = ruff src tests examples
 description = Run ruff over src, test, exampless
 
 [pytest]
-addopts = 
+addopts =
     --color=yes
     --strict-markers
-    --strict-config 
+    --strict-config
     -ra
 
 testpaths = tests


Test patch:
diff --git a/src/pytest_check/plugin.py b/src/pytest_check/plugin.py
index 2ebda72..67b36f4 100644
--- a/src/pytest_check/plugin.py
+++ b/src/pytest_check/plugin.py
@@ -40,14 +40,28 @@ def pytest_runtest_makereport(item, call):
                 raise AssertionError(report.longrepr)
             except AssertionError as e:
                 excinfo = ExceptionInfo.from_current()
-                e_str = str(e)
-                # will be 5 with color, 0 without
-                if e_str.find('FAILURE: ') in (0, 5):
-                    e_str = e_str.split('FAILURE: ')[1]
-                reprcrash = ReprFileLocation(item.nodeid, 0, e_str)
-                reprtraceback = ExceptionRepr(reprcrash, excinfo)
-                chain_repr = ExceptionChainRepr([(reprtraceback, reprcrash, str(e))])
-                report.longrepr = chain_repr
+                if pytest.version_tuple >= (7,3,0):
+                    # Build a summary report with failure reason
+                    # Depends on internals of pytest, which changed in 7.3
+                    #
+                    # Example: Before 7.3:
+                    #   =========== short test summary info ===========
+                    #   FAILED test_example_simple.py::test_fail
+                    # Example after 7.3:
+                    #   =========== short test summary info ===========
+                    #   FAILED test_example_simple.py::test_fail - assert 1 == 2
+                    #
+                    e_str = str(e)
+                    e_str = e_str.split('FAILURE: ')[1]  # Remove redundant "Failure: "
+                    reprcrash = ReprFileLocation(item.nodeid, 0, e_str)
+                    reprtraceback = ExceptionRepr(reprcrash, excinfo)
+                    chain_repr = ExceptionChainRepr([(reprtraceback, reprcrash, str(e))])
+                    report.longrepr = chain_repr
+                else:  # pragma: no cover
+                    # coverage is run on latest pytest
+                    # we'll have one test run on an older pytest just to make sure
+                    # it works.
+                    ...
 
             call.excinfo = excinfo
 
@@ -55,7 +69,7 @@ def pytest_runtest_makereport(item, call):
 def pytest_configure(config):
     # Add some red to the failure output, if stdout can accommodate it.
     isatty = sys.stdout.isatty()
-    color = config.option.color
+    color = getattr(config.option, "color", None)
     check_log.should_use_color = (isatty and color == "auto") or (color == "yes")
 
     # If -x or --maxfail=1, then stop on the first failed check
@@ -69,9 +83,9 @@ def pytest_configure(config):
     check_log._stop_on_fail = stop_on_fail
 
     # Allow for --tb=no to turn off check's pseudo tbs
-    traceback_style = config.getvalue("tbstyle")
+    traceback_style = config.getoption("tbstyle", default=None)
     pseudo_traceback._traceback_style = traceback_style
-    check_log._showlocals = config.getvalue('showlocals')
+    check_log._showlocals = config.getoption("showlocals", default=None)
 
     # grab options
     check_log._default_max_fail = config.getoption("--check-max-fail")
diff --git a/tests/test_summary.py b/tests/test_summary.py
index 871d08a..d1724bb 100644
--- a/tests/test_summary.py
+++ b/tests/test_summary.py
@@ -1,9 +1,19 @@
+import pytest
+
+
+require_pytest_7_3 = pytest.mark.skipif(
+    pytest.version_tuple < (7, 3, 0),
+    reason="summary message only supported on pytest7.3+")
+
+
+@require_pytest_7_3
 def test_baseline(pytester):
     pytester.copy_example("examples/test_example_summary.py")
     result = pytester.runpytest("-k check_no_msg")
     result.stdout.fnmatch_lines(["*FAILED*-*check 1 == 2*"])
 
 
+@require_pytest_7_3
 def test_message(pytester):
     pytester.copy_example("examples/test_example_summary.py")
     result = pytester.runpytest("-k check_msg")