pytest-dev/pytest · error · TypeError

cannot compare ' ' to numpy.ndarray

Error message

cannot compare '{actual}' to numpy.ndarray

What it means

When approx() wraps a numpy array, ApproxNumpy.__eq__ tries to convert the compared value to an ndarray via np.asarray(actual). If that conversion raises any exception (the actual value is not array-like), pytest re-raises it as this TypeError, chaining the original cause. This protects the comparison from silently returning False on genuinely incompatible operands.

Solutions

  1. Ensure the actual value is array-like (list, tuple, or numpy array) before comparing: `assert np.asarray(actual) == approx(np.array([...]))`.
  2. Convert both sides explicitly with np.asarray so the failure happens with a clearer traceback.
  3. If comparing a single scalar to an array, compare against approx(scalar) instead of approx(array).

Example fix

# before
assert {'a': 1} == approx(np.array([1.0, 2.0]))
# after
assert np.array([1.0, 2.0]) == approx(np.array([1.0, 2.0]))
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def is_array_compatible(value) -> bool:
    if np.isscalar(value):
        return True
    try:
        np.asarray(value)
        return True
    except Exception:
        return False
# usage
if is_array_compatible(actual):
    assert actual == approx(np_array)

Type guard

import numpy as np
def is_ndarray_or_scalar(v) -> bool:
    return np.isscalar(v) or isinstance(v, np.ndarray)

Try / catch

try:
    assert actual == approx(np_array)
except TypeError as e:
    if 'cannot compare' in str(e):
        raise AssertionError(f'actual not array-like: {actual!r}') from e
    raise

Prevention

When it happens

Trigger: Calling approx(np.array([1.0,2.0])) == some_object where some_object is a dict, a string, an object without __array__, or a ragged/nested structure numpy cannot broadcast. Triggered at ApproxNumpy.__eq__ (src/_pytest/approx.py:218-227) only when the expected value was itself a numpy array (or array-like with numpy imported).

Common situations: Comparing an array approximation against a dict/None/string; mixing array and scalar-with-mixed-types; passing an object that implements __array__ but raises internally; using a mock or custom container as the actual value.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/0a68515ae8a245d8. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/approx.py:227

        return _compare_approx(
            self.expected,
            message_data,
            number_of_elements,
            different_ids,
            max_abs_diff,
            max_rel_diff,
        )

    def __eq__(self, actual) -> bool:
        import numpy as np

        # self.expected is supposed to always be an array here.

        if not np.isscalar(actual):
            try:
                actual = np.asarray(actual)
            except Exception as e:
                raise TypeError(f"cannot compare '{actual}' to numpy.ndarray") from e

        if not np.isscalar(actual) and actual.shape != self.expected.shape:
            return False

        return super().__eq__(actual)

    def _yield_comparisons(self, actual):
        import numpy as np

        # `actual` can either be a numpy array or a scalar, it is treated in
        # `__eq__` before being passed to `ApproxBase.__eq__`, which is the
        # only method that calls this one.

        if np.isscalar(actual):
            for i in np.ndindex(self.expected.shape):
                yield actual, self.expected[i].item()
        else:
            for i in np.ndindex(self.expected.shape):

View on GitHub (pinned to 0d6fbdeffa)