Skip to content

Instantly share code, notes, and snippets.

@kernc
Last active February 6, 2016 14:35
unittest.TestSuite module that recursively loads all doctests from my package
"""
unittest.TestSuite module that recursively loads all doctests from my package
"""
from doctest import DocTestSuite, ELLIPSIS, NORMALIZE_WHITESPACE
SKIP_DIRS = (
'MyPackage/unimportable-modules/',
'MyPackage/skip_this_too',
)
def find_modules(package):
"""Return a recursive list of submodules for a given package"""
from os import path, walk
module = path.dirname(getattr(package, '__file__', package))
parent = path.dirname(module)
files = (path.join(dir, file)[len(parent) + 1:-3]
for dir, dirs, files in walk(module)
for file in files
if file.endswith('.py'))
files = (f for f in files if not f.startswith(SKIP_DIRS))
files = (f.replace(path.sep, '.') for f in files)
return files
class Context(dict):
"""
Execution context that *retains* the changes the tests make. Preferably
use one per module to obtain nice "literate" modules that "follow along".
In other words, directly the opposite of:
https://docs.python.org/3/library/doctest.html#what-s-the-execution-context
By popular demand:
http://stackoverflow.com/questions/13106118/object-reuse-in-python-doctest/13106793#13106793
http://stackoverflow.com/questions/3286658/embedding-test-code-or-data-within-doctest-strings
"""
def copy(self):
return self
def clear(self):
pass
def suite(package):
"""Assemble test suite for doctests in path (recusrively)"""
from importlib import import_module
for module in find_modules(package.__file__):
try:
module = import_module(module)
yield DocTestSuite(module
globs=Context(module.__dict__.copy()),
optionflags=ELLIPSIS | NORMALIZE_WHITESPACE)
except ValueError:
pass # No doctests in module
except ImportError:
import warnings
warnings.warn('Unimportable module: {}'.format(module))
def load_tests(loader, tests, ignore):
# This follows the load_tests protocol
# https://docs.python.org/3/library/unittest.html#load-tests-protocol
import MyPackage
tests.addTests(suite(MyPackage))
return tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment