[Python-ideas] Overloading operators for testing
Steven D'Aprano
steve at pearwood.info
Tue Sep 20 10:12:23 EDT 2016
On Sun, Sep 18, 2016 at 02:52:31AM +0200, Arek Bulski wrote:
> I am using declarative testing a lot and I found out why unit tests are so
> clunky.
I don't think unit tests are clunky.
> The reason why assertEquals(a,b) is used is because if we put
> `assert a==b` then nose can catch the AssertionError but wont find out what
> was returned or expected.
That's not the only reason.
assert* methods can take an arbitrary number of arguments. == cannot.
It is easy to extend the collection of assert* methods, to use
inheritance to modify them, and so on. Not so easy if you have only a
single, global function or operator.
assert* methods can run even when assertions are disabled.
> This could be easily overcome if we allow
> oveloading == operator from outside. Right now == would have to be changed
> for every lefhand object that is compared in the tests, builtin types
> including. We could use a way to change it from above, so to speak.
Having global state that controls the behaviour of == is not a good
idea. Look at your proposed code:
> Consider this:
>
> def __glob_eq__(a,b):
> if not a == b:
> raise FoundInequalityError(a,b)
> return True
>
> assert obj1 == obj2 #<-- using eq above
That can't work as you have written it, because it will recurse forever.
obj1 == obj2 will call the global eq, which calls == which calls the
global eq, which calls == which calls the global eq.
So let's re-write it:
def __glob_eq__(a,b):
saved_state = get_global_eq()
delete_global_eq()
try:
if not a == b: # calls the real ==
raise FoundInequalityError(a,b)
return True
finally:
set_global_eq(saved_state)
Okay, that's pretty yucky, and its not thread-safe, but at least its
only in one place, right? Except it isn't. Every single call to == (and
!= ) will have to be re-written to do the same thing.
And of course, that just replaces assertEquals. What about all the other
assert* methods?
But there's another, more fundamental problem with using assert in this
way. You cannot run your unit tests with assertions turned off.
That is why I think the nose style of using "assert a == b" for unit
testing is seriously broken. That is an abuse of the assert statement.
It's good enough for a handful of quick and dirty tests, but is not good
enough for a full-sized unit test suite.
--
Steve
More information about the Python-ideas
mailing list