On Sun, Jul 26, 2020 at 12:31:17PM -0500, Henry Lin wrote:
> Hi Steven,
> 
> You're right, declaring `__eq__` for the class we want to compare would
> solve this issue. However, we have the tradeoff that
> 
>    - All classes need to implement the `__eq__` method to compare two
>    instances;

One argument in favour of a standard solution would be to avoid 
duplicated implementations. Perhaps we should add something, not as a 
unittest method, but in functools:

    def compare(a, b):
        if a is b:
            return True
        # Simplified version.
        return vars(a) == vars(b)

The actual implementation would be more complex, of course. Then classes 
could optionally implement equality:


    def __eq__(self, other):
        if isinstance(other, type(self):
            return functools.compare(self, other)
        return NotImplemented

or if you prefer, you could call the function directly in your unit 
tests:

    self.assertTrue(functools.compare(actual, other))



>    - Any class implementing the `__eq__` operator is no longer hashable

Easy enough to add back in:

    def __hash__(self):
        return super().__hash__()


>    - Developers might not want to leak the `__eq__` function to other
>    developers; I wouldn't want to invade the implementation of my class just
>    for testing.

That seems odd to me. You are *literally* comparing two instances for 
equality, just calling it something different from `==`. Why would you 
not be happy to expose it?


> In terms of the "popularity" of this potential feature, from what I
> understand (and through my own development), there are testing libraries
> built with this feature. For example, testfixtures.compare
> <https://testfixtures.readthedocs.io/en/latest/api.html#testfixtures.compare>
> can compare two objects recursively, and I am using it in my development
> for this purpose.

That's a good example of what we should *not* do, and why trying to 
create a single standard solution for every imaginable scenario can only 
end up with an over-engineered, complex, complicated, confusing API:

    testfixtures.compare(
        x, y,
        prefix=None, 
        suffix=None, 
        raises=True, 
        recursive=True, 
        strict=False, 
        comparers=None, 
        **kw)

Not shown in the function signature are additional keyword arguments:

    actual, expected # alternative spelling for x, y
    x_label,
    y_label,
    ignore_eq

That is literally thirteen optional parameters, plus arbitrary keyword 
parameters, for something that just compares two objects.

But a simple comparison function, possibly in functools, that simply 
compares attributes, might be worthwhile.



-- 
Steven
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/56GD3DDO2PLNOB4TIIO7PBJCUPFLGA3V/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to