Python: using doctests for classes
You're missing the code to actually run the doctests at the bottom of the file:
class Test:
<snip>
if __name__ == "__main__":
import doctest
doctest.testmod()
As for where to put the tests:
- If it's testing the class as a whole, I'd put them in the class' docstring.
- If it's testing the constructor, I'd put them in the constructor's docstring.
- If it's testing a method (as it seems to be in this case), I'd actually put it them in that method's docstring.
doctest doesn't test classes methods in a module
I found out why.
Why it doesn't work
doctest tries to detect which tests don't belong to the tested module, and doesn't run them. This prevents running all the tests of your dependencies.
Here, my doctest belongs to simplemod.A
while I am testing simplemod
.
Recommended solution
From the doctest documentation about testing complex packages.
Rename A.py
to a.py
, and replace __init__.py
, with
from . import a
def load_tests(loader, tests, ignore):
import unittest
import doctest
tests.addTests(doctest.DocTestSuite(a))
return tests
You can then run your test with a simple
$ python -m unittest
in the parent folder.
Using doctest on class property with py.test
Finally I found that the test doesn't pass only when I do right click/Run 'Doctest attribute_squared' in Pycharm.
When running pytest, the test passes.
Python: How can I define a class in a doctest?
Try it out in the interpreter; it uses ...
to show continuation lines. >>>
is only for a new statement or expression, while a class
in incomplete until you've had an empty ...
continuation line:
>>> class A(MyClass):
... def __init__(self):
... super(A, self).__init__()
...
Executing Python doctest code
The difference is that when you execute via doctest
, it is the __main__
module compared to executing directly where your script's if __name__ == '__main__'
block will execute.
I don't know of a good solution other than to put all the information you need in the docstring itself:
def multiply_by_2(self):
"""
>>> t = Test(2)
>>> t.multiply_by_2()
4
"""
return self._number * 2
This will have the added benefit that users who are reading your docstrings will know what's going on ... They won't have to stumble upon your extraglobs
keyword to figure out what t
is and how it was initialized.
Suppressing doctest in abstract or Protocol classes
Your doc test has to do the same thing a user would be expected to do: define a subclass that implements do_something
and instantiate that class.
class MyABC(ABC):
"""My docstring.
Here is a recommended use case for this item:
Examples:
>>> class Foo(MyABC):
... def do_something(self):
... return 'some expected behaviour'
...
>>> a = Foo()
>>> a.do_something()
'some expected behaviour'
"""
@abstractmethod
def do_something(self):
pass
Related Topics
Anaconda Installed But Cannot Launch Navigator
In Python, How to Check If a Date Is Valid
How to Disable Pylint Unused Import Error Messages in VS Code
Ssl: Certificate_Verify_Failed With Python3
Could Not Find a Version That Satisfies the Requirement in Python
Removing Punctuations and Spaces in a String Without Using Regex
How to Add a Delay to Message.Delete()
Faster Way to Read Excel Files to Pandas Dataframe
Python: Split a List into Multiple Lists Based on a Subset of Elements
Python: Using Doctests for Classes
Creating a New Dataframe Column by Comparing Strings of Two Unequal Dataframes
Get Max Value Comparing Multiple Columns and Return Specific Values
How to Read a Column Without Header from CSV and Save the Output in a Txt File Using Python
How to Convert a Datetime Object to Milliseconds Since Epoch (Unix Time) in Python
Find Matching Rows in 2 Dimensional Numpy Array
How to Write 2 Lists of Items in 2 Columns Instead of 2 Arrays