Skip to content

pytest.approx loses mismatch details for same-key mappings with unequal strings #15009

Open

Description

@torjan0

pytest.approx supports non-numeric mapping values, but unequal strings under the same key cause its assertion diagnostic formatter to raise TypeError.

Save as test_approx_mapping.py:

import pytest


def test_mapping_string_mismatch():
    assert {"item": "a"} == pytest.approx({"item": "b"})

Run python -m pytest -q test_approx_mapping.py.

The assertion fails as expected, but its details are replaced by this message (local source path omitted):

(pytest_assertion plugin: representation of details failed: ... TypeError: unsupported operand type(s) for -: 'str' and 'str'.
 Probably an object has a faulty __repr__.)

Expected: a failed assertion with mapping mismatch details and no internal formatter exception. The equivalent unequal-string sequence retains its detail table.

#13010 and #13012 cover sequences; #13816 concerns different mapping keys. This example uses identical keys.

Reproduced on pytest 9.1.1 and development commit 3fd8675d6d798507c06cf9c60753be6d9d7b0e17, with CPython 3.12.3 on Linux 6.8.0-100-generic x86-64.

Installed packages (uv pip list --offline; this environment has no pip module):

Package          Version
---------------- -------
attrs            26.1.0
hypothesis       6.168.0
iniconfig        2.3.0
numpy            2.5.3
packaging        26.3
pluggy           1.6.0
pygments         2.21.0
pytest           9.1.1
sortedcontainers 2.4.0

GPT-6 Astra assisted; I manually reviewed this report.

Activity

  1. deepak7lal commented on Sep 13, 2026

    @deepak7lal

    I'd like to take this. Reproduced on main, and the cause is a small asymmetry between the mapping and sequence formatters.

    ApproxMapping._repr_compare (src/_pytest/approx.py) guards the diff arithmetic with:

    except ZeroDivisionError:
        pass

    while ApproxSequenceLike._repr_compare guards the equivalent block with except TypeError, added in #13012 for #13010. Subtracting two strings raises TypeError, so the mapping path lets it escape into the assertion-repr hook, which is why the details are replaced by the "representation of details failed" message while the sequence equivalent still prints its table:

    # mapping  -> TypeError: unsupported operand type(s) for -: 'str' and 'str'
    # sequence -> Index | Obtained | Expected
    #             1     | a        | b
    

    Plan, following #13012:

    • Widen the guard to except (ZeroDivisionError, TypeError) so non-numeric values are skipped for the max-abs/max-rel calculations but still reported in the mismatch table.
    • Add a mapping test in testing/python/approx.py alongside test_mixed_sequence, covering both an all-string mapping and a mixed numeric/string mapping.
    • Add a changelog/ entry.

    I'll keep #15010 out of scope since that one is about the Decimal tolerance repr rather than the formatter raising.

  2. added a commit that references this issue on Sep 14, 2026
    01281a1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions