Home
djfroofy
January 31st, 2008 

Advertisement

Customize
avatar

I used to think python doctests were the greatest thing since sliced bread. I no longer think this and I've returned to the basics (most of the time): plain old unittests. So let me explain why.

This is the crux of the matter: documents are supposed to be documents and readable as such. Too often I see doctests that stray from readability in favor of including chunks of code which achieve testability - test set up, tear down, white space stripping ... For example, let's look at a part of README.txt in zope.event (and the Zope camp definitely embraces doctests):

The package has a list of subscribers.  Application code can manage
subscriptions by manipulating this list.  For the examples here, we'll
save the current contents away and empty the list. We'll restore the
contents when we're done with our examples.

  >>> import zope.event
  >>> old_subscribers = zope.event.subscribers[:]
  >>> del zope.event.subscribers[:]

This isn't documentation! You're wasting time (your time and mine) explaining something to me that has nothing to with how to use the interface. doctest does provide facilities for executing setUp and tearDown functions in regular python modules prior to executing a test, but I seldom see this approach taken. Why? Well I guess this requires more work, and it seems the appeal with doctests is doing less work. I can relate, and even took a crack once at automating specification of setUp/tearDown functions: http://xix.python-hosting.com/file/trunk/xix/utils/test.py .

And while we're on the subject of code I've written, here's another example of a bad doctest:

>>> action.addMessageCategoryCallback(thread1, t1)
>>> action.addMessageCategoryCallback(thread2, t2)
>>> action.addMessageCategoryCallback(metaname, mname)
>>> from loggrok.log import LogStream
>>> stream = LogStream(fname)
>>> stream.messageParser = parser
>>> stream.action = action
>>> for entry in stream:
...     continue
...
====
THREAD1 C
D E
F G
H I
====
THREAD1 J K
====
THREAD2 L M
N
====

WTF? This isn't a document! This is a plain old unittest, disguised as a document! Stop wasting my time!

Okay, so I've been a little harsh. I've tried hard to rant as little as possible on this blog, but today I've fallen short of that goal. But please don't get what I'm saying wrong. I'm not asserting that doctests are useless and you should never use them. (Har har! Get it? "I'm not asserting ...") In fact doctests can be great but I don't think they're effective for fully testing an application - since this will always conflict with writing apt and succinct documentation. What they are good for, if I can suggest, is to verify that examples in a documentation don't contain syntactic errors and are up to date with the current code base. Of course some setUp and tearDown routines may be needed to ensure the examples actually work or don't leave the interpreter in bad state when complete, but there are several approaches to not revealing this in the document (for example, put the setUp/tearDown in comments or use the facilities providing by the doctest library to execute such functions).

On side note, it really isn't worth fussing about, at least on a policy level. If someone on your team is writing unittests (be it doctests or old school unittest), it's best to hold your lip and not engage in bickering about what format they should be in. What matters most is that the application is being tested and the project is approaching good line and combinatorial branch coverage.

Advertisement

Customize
This page was loaded Mar 19th 2010, 7:34 am GMT.