1

I want to run doc-tests of a Python script as part of a pre-commit hook in Python.

In the file set_prefix.py, I have doc-tests in front of functions, which I test before running with:

import doctest
import sys

EXTENSIONS = tuple([".%s" % ending for ending in ["jpg", "heic", "nrw"]])

def is_target_for_renaming(filepath):
    """Returns true if this filepath should be renamed.

    >>> is_target_for_renaming("/Users/username/Pictures/document.other_jpg")
    True
    """

    return filepath.lower().endswith(EXTENSIONS)


def get_failed_tests():
    r = doctest.testmod()
    return r.failed


def main():
    pass


if "__main__" == __name__:

    args = sys.argv
    test_only = 2 <= len(sys.argv) and "test" == sys.argv[1]
    test_failures = get_failed_tests()
    print(test_failures)
    assert 0 == test_failures

    if not test_only:
        main()

When I run python3 set_prefix.py test, I get the error I expected.

Yet, when I import the module and call the function:

import set_prefix

if "__main__" == __name__:

    test_failures = set_prefix.get_failed_tests()
    print(test_failures)

I get 0 failures:

$ python3 temp.py 
0

The reason I want to import the module is to run the tests in a pre-commit hook similar to that added by flake8:

#!/usr/local/opt/python/bin/python3.7
import sys

from flake8.main import git

if __name__ == '__main__':
    sys.exit(
        git.hook(
            strict=git.config_for('strict'),
            lazy=git.config_for('lazy'),
        )
    )

Why do the doc-tests run when called from the command-line and the script and not when the script is imported? Would unittest be a better framework, as described in this thread?

miguelmorin
  • 5,025
  • 4
  • 29
  • 64

1 Answers1

1
doctest.testmod()

runs doctests in __main__ module and it depends on which script you're actually running.

You can fix this with m parameter, but you'll still be forced to add boilerplate code in each module that has doctests. Try this:

doctest.testfile("some_module.py")
RafalS
  • 5,834
  • 1
  • 20
  • 25
  • With code `doctest.testfile("module.py")`, I get many `NameError: name '...' is not defined`, even though the tests run OK when called from the module itself with `python3 module.py`. – miguelmorin Apr 14 '20 at 11:19
  • Sounds weird, can you paste a specific NameError? – RafalS Apr 14 '20 at 14:28
  • I couldn't get the right formatting in a comment. Here's one error: ```File "", line 1, in is_target_for_renaming("/Users/username/Pictures/document.other_jpg") NameError: name 'is_target_for_renaming' is not defined``` and `set_prefix.py` has ```def is_target_for_renaming(filepath): """ >>> is_target_for_renaming("/Users/username/Pictures/document.other_jpg") False ``` – miguelmorin Apr 15 '20 at 10:36