[Python-Dev] Purpose of Doctests [Was: Best practices for Enum]

Olemis Lang olemis at gmail.com
Tue May 21 01:35:34 CEST 2013


Hi !
... sorry , I could not avoid to reply this message ...

On 5/20/13, Michael Foord <fuzzyman at voidspace.org.uk> wrote:
>
> On 20 May 2013, at 18:26, Mark Janssen <dreamingforward at gmail.com> wrote:
>
>>>> I'm hoping that core developers don't get caught-up in the "doctests are
>>>> bad
>>>> meme".
>>>>
>>>> Instead, we should be clear about their primary purpose which is to
>>>> test
>>>> the examples given in docstrings.
>>>> In other words, doctests have a perfectly legitimate use case.
>>>
>>> But more than just one ;-)  Another great use has nothing to do with
>>> docstrings:  using an entire file as "a doctest".   This encourages
>>> writing lots of text explaining what you're doing,. with snippets of
>>> code interspersed to illustrate that the code really does behave in
>>> the ways you've claimed.
>>
>> +1, very true.  I think doctest excel in almost every way above
>> UnitTests.  I don't understand the popularity of  UnitTests, except
>> perhaps for GUI testing which doctest can't handle.  I think people
>> just aren't very *imaginative* about how to create good doctests that
>> are *also* good documentation.
>>
>

With enhanced doctests solution in mind ...

> Doc tests have lots of problems for unit testing.
>
> * Every line is a test with *all* output part of the test - in unit tests
> you only assert the specific details you're interested in

custom output checkers

> * Unordered types are a pain with doctest unless you jump through hoops

( custom output checkers + doctest runner ) | (dutest __tc__ global var)

> * Tool support for editing within doctests is *generally* worse

this is true , let's do it !

> * A failure on one line doesn't halt execution, so you can get many many
> reported errors from a single failure

it should if REPORT_ONLY_FIRST_FAILURE option [1]_ is set .

> * Try adding diagnostic prints and then running your doctests!

I have ... dutest suites for my Trac plugins do so . However logging
information is outputted to /path/to/trac/env/log/trac.log ... so a
tail -f is always handy .

> * Tools support in terms of test discovery and running individual tests is
> not as smooth

dutest offers two options since years ago MultiTestLoader combines
multiple test loaders to *load* different kinds of tests at once from
a module , whereas a package loader performs test discovery . These
loader objects are composable , so if an instance of MultiTestLoader
is supplied in to the package test loader then multiple types of tests
are loaded out of modules all over across the package hierarchy .

Indeed , in +10 years of Python development I've never used
unittest(2) discovery, and even recently implemented the one that's
used in Apache™ Bloodhound test suite . Unfortunately I've had no much
time to spend on improving all this support in dutest et al.

> * Typing >>> and ... all the time is really annoying

... I have faith ... there should be something like this for vim ... I
have faith ... ;)

> * Doctests practically beg you to write your code first and then copy and
> paste terminal sessions - they're the enemy of TDD

Of course , not , all the opposite . If the approach is understood
correctly then the first thing test author will do is to write the
code «expected» to get something done . When everything is ok with API
code style then write the code . Many problems in the API and
inconsistencies are thus detected early .

> * Failure messages are not over helpful and you lose the benefit of some of
> the new asserts (and their diagnostic output) in unittest

(custom ouput checkers) | ( dutest __tc__ variable )

> * Tests with non-linear code paths (branches) are more painful to express in
> doctests
>

that's a fact , not just branches , but also exceptions

Beyond this ...

My really short answer is that I do not agree with this . Like I just
said in previous messages with enhanced support like the one offered
by dutest (i.e. __tc__ global var bound to an instance of
unittest.TestCase) it's possible to invoke each and every unittest
assertion method . So this may be seen all the other way round
«unittest machinery is already used without even declaring a single
test class» ... and so on ...

... so , in concept , there is no real benefit in using unittest over
doctest *if* doctest module is eventually upgraded .

[...]
>
> However doctests absolutely rock for testing documentation / docstring
> examples.
>

FWIW , +1

[...]

.. [1] doctest.REPORT_ONLY_FIRST_FAILURE
        (http://docs.python.org/2/library/doctest.html#doctest.REPORT_ONLY_FIRST_FAILURE)

-- 
Regards,

Olemis.

Apache™ Bloodhound contributor
http://issues.apache.org/bloodhound

Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/

Featured article:


More information about the Python-Dev mailing list