pythonpytestdoctest

Mixing py.test and doctests


Many of my tests are written in py.test where it makes sense:

def test_some_function():
    assert some_function() == 42

Some other user directed functions end up having doctests because they will show up in the documentation:

def snub(k):
    """
    Snub will deflarg your booblebum.

    >>> snub(10)
    20
    >>> snub('tomorrow')
    'carrot'

    :param any k: The transspace to deflarg.
    :returs any:
    """    
    # ...

I know that with --doctest-modules I can get pytest to run the doctests but I have not yet found a way of running all tests at the same time.

What I want is something like:

all_tests.py

from my_module import snub  # now this should be enough to run the doctests

def test_some_function():
    assert some_function() == 42

Is there any way of accomplishing this? Am I missing something?

I would also gladly use some kind of generator where I can input the functions that have doctests to run.


Solution

  • If you have your tests in a separate folder, than your python module, as in the following structure:

    my-project
    ├── mylib
    │   └── mymod.py
    └── tests
        └── test_mymod.py
    

    The key to make pytest discover everything, is to give it enough information. You can simply specify both folders on the command line for discovery:

    pytest --doctest-modules mylib tests
    

    To make this a bit more comfortable you can set the testpaths config-variable for pytest, and also include the doctest argument by default. An example pyproject.toml:

    [tool.pytest.ini_options]
    addopts = "--doctest-modules"
    testpaths = [
        "tests",
        "mylib",
    ]
    

    pytest will recursively walk through the folders to discover the tests.