I want to have a doctest for a class, where the use of the class needs a somehow lengthy setup. Like:
class MyClass
def __init__(self, foo):
self.foo = foo
def bar(self):
"""Do bar
>>> # do a multiline generation of foo
... ...
>>> myoby = MyClass(foo)
>>> print(myobj.bar())
BAR
"""
…
def foobar(self):
"""Do foobar
>>> # do a multiline generation of foo
... ...
>>> myoby = MyClass(foo)
>>> print(myobj.foobar())
FOOBAR
"""
…
My real case has ~8 methods that I want to document and pytest. Repeating the generation of foo everywhere contradicts the DRY principle, and also generated quite lengthy and unreadable documentation. Is there a way to avoid it?
Optimally would be like
class MyClass
"""My class
An example way to create the 'foo' argument is
>>> # do a multiline generation of foo
... ...
"""
def __init__(self, foo):
self.foo = foo
def bar(self):
"""Do bar
>>> myoby = MyClass(foo)
>>> print(myobj.bar())
BAR
"""
…
def foobar(self):
"""Do foobar
>>> myoby = MyClass(foo)
>>> print(myobj.foobar())
FOOBAR
"""
…
After some struggling, I found the following solution, (ab)using a submodule of my own module:
class MyClass
"""My class
An example way to create the 'foo' argument is::
>>> # do a multiline generation of foo
>>> foo = ...
.. only:: doctest
>>> import mymodule.tests
>>> mymodule.tests.foo = foo
"""
def __init__(self, foo):
self.foo = foo
def bar(self):
"""Do bar
.. only:: doctest
>>> import mymodule.tests
>>> foo = mymodule.tests.foo
Here is a good example, using the initialization above::
>>> myoby = MyClass(foo)
>>> print(myobj.bar())
BAR
"""
…
The "tricks":
I abuse my mypackage.tests
submodule to store the results of the initialization. This works, since the modules are not re-initialized in subsequent tests
Doctest (at least in pytest) doesn't care about code blocks, it just looks for the appropriate patterns and indentions. Any block is fine, even a conditional one (.. only::
). The condition (doctest
) is arbitrary, it just needs to be evaluated to false so that the block isn't displayed.
I am still not sure how robust this is with respect to future developments of doctest/pytest and sphinxdoc.