I had great hopes for this when I saw the title. I normally use TDD (Test Driven Development) exclusively, but have been finding it difficult to get into the rhythm of TDD when developing in Python for Google App Engine. I’m just not familiar enough with the Python unit-test ecosystem. So a general purpose Mock Object framework looked as if it would be a useful tool for the toolbox.
Unfortunately, it uses my least favourite approach to Mock Objects: switch the Mock into “record” mode, manually perform a sequence of actions, then switch the mock to “replay” mode and run the real code to compare it against the recorded expectations.
In the Java world this is the approach taken by EasyMock. In a strongly-typed, pre-compiled language such as Java, this is just about excusable in order to gain method call validation in the IDE or compiler. But in a more flexible language I really can’t see the point.
For me, the overwhelming disadvantage of the record-replay approach is that it implies that there is only one complete correct sequence of collaboration calls, and that anything else is an error. In real systems this is simply not true. Some calls might be optional (such as a “getter” which may be cached”); some calls may be unimportant to a particular test; some calls may be happily repeated many times (such as a “hasMore” or equivalent status call); and most importantly, some calls may occur in any order.
Although typical record-reply frameworks try to address some of these issues, every such attempt makes the operation of the framework more clumsy and less obvious. It’s very hard to address the fundamental problem.
In my opinion, a much better approach to mock objects is for the Mock object to simply record all the calls made during the running of the test, and then provide a flexible set of accessors and assertions to apply to the result. That way, whoever writes the test case can also easily write specific assertions, such as asserting that the count of calls to “hasNext” is always one more than the count of calls to “next” without requiring special support in the framework.
Does anyone know of a more sensible Mock framework for Python?