Beginners' Guide to Effortless Doctests in Python
A Software Engineer passionate about public good projects and making technology to serve society en masse.
Search for a command to run...
A Software Engineer passionate about public good projects and making technology to serve society en masse.
No comments yet. Be the first to comment.
HS (Harmonised System) Codes help classify customs authorities and businesses around the world to ensure appropriate import/export control. This system recursively classifies a product into finer granularity of categories. Figure 1: A simple exercis...
Jan allows you to deploy and run LLMs on your Windows or macOS computer! 16 Gigabytes of memory and a M1 chip was enough for me to run Mistral locally. Now how do you take Jan and use libraries like Langchain? https://jan.ai Local API Server Click ...
My talk at PyCon Thailand 2023 on the security aspects and possible attack vectors of LLM Applications, tailored to both product people and engineers! https://youtu.be/_fvk_Qa5OsM Thank you PyCon TH team!
Looking for a flat for rent, with LLMs
Code generators replace mindless coding with productivity; a pure function that produces predictable code, given a (set of) input(s). Generating boilerplate classes or templates — a common use case for Codegen. Use-case: Generating Classes We will be...
Doctests are essentially tests embedded in a docstring. They serve both as example use cases and test cases! A Python expression is provided along with an expected outcome, a test runner collects that and evaluates the expression.
Let's take a look at a run-of-the-mill docstring.
def hello(name):
"""
Returns a greeting message saying Hello.
:param name: str
:return: str
"""
return 'Hello, ' + name
It's a normal docstring with nothing too special. Let's try to get the doctest module to test our test-less function.
$ python -m doctest -v hello.py
2 items had no tests:
hello
hello.hello
0 tests in 2 items.
0 passed and 0 failed.
Test passed.
Well, the output says it clear that we have no tests. Now, let's add a doctest. Remember how the Python Shell or REPL works? Remember how you have three arrows indicating input? Yes. Just copy that style.
def hello(name):
"""
Returns a greeting message saying Hello.
:param name: str
:return: str
>>> hello('Anam')
'Hello, Anam'
"""
return 'Hello, ' + name
Time to run the doctest module again.
$ python -m doctest -v hello.py
Trying:
hello('Anam')
Expecting:
'Hello, Anam'
ok
1 items had no tests:
hello
1 items passed all tests:
1 tests in hello.hello
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
Ah, that looks more like it.
Let's try something more fun. Let's add a case in our function, if the provided name is just composed of digits, we refuse to greet digits!
def hello(name):
"""
Returns a greeting message saying Hello.
:param name: str
:return: str
>>> hello('Anam')
'Hello, Anam'
"""
if name.isdigit():
raise ValueError('We do not greet numbers')
return 'Hello, ' + name
Now, how do we test for exceptions? Well, remember the mantra.
Replicate your shell; success you will be showered with upon you.
So, just replicate your shell! Let's see how the shell reacts to digits.

So, in the doctest,
def hello(name):
"""
Returns a greeting message saying Hello.
:param name: str
:return: str
>>> hello('Anam')
'Hello, Anam'
>>> hello('121')
Traceback (most recent call last):
...
ValueError: We do not greet numbers
"""
if name.isdigit():
raise ValueError('We do not greet numbers')
return 'Hello, ' + name
Just the first line and the last line of the exception. Don't confuse doctest with a complete, well-formatted and fully laid out stack trace, please! And just three dots to indicate there were more to it. So, let's run this again.
$ python -m doctest -v hello.py
Trying:
hello('Anam')
Expecting:
'Hello, Anam'
ok
Trying:
hello('121')
Expecting:
Traceback (most recent call last):
...
ValueError: We do not greet numbers
ok
1 items had no tests:
hello
1 items passed all tests:
2 tests in hello.hello
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
And yes.
Of course, in production, you do need to use a test runner. Something in the category of pytest or nose. I personally prefer pytest. Let's take a look at configuring pytest for this.

Not so surprisingly, it discovered no tests in the default configuration. We need to add a simple flag to it --doctest-modules .

That seems to be working, let's try to intentionally run our tests to check if it is really working.

And that is working perfectly. To avoid putting the --doctest-modules flag all the time, consider making a tox.ini file to place your pytest configuration. More on this in the pytest documentation.