Last active
February 6, 2016 14:35
-
-
Save kernc/0dccae6542465d59a331 to your computer and use it in GitHub Desktop.
unittest.TestSuite module that recursively loads all doctests from my package
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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