1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
import sys
import os
from doctest import DocTestSuite, ELLIPSIS, NORMALIZE_WHITESPACE
SKIP_DIRS = (
# Skip modules which import and initialize stuff that require QApplication
'Orange/widgets',
'Orange/canvas',
# Skip because we don't want Orange.datasets as a module (yet)
'Orange/datasets/'
)
if sys.platform == "win32":
# convert to platform native path component separators
SKIP_DIRS = tuple(os.path.normpath(p) for p in SKIP_DIRS)
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 (recursively)"""
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 Orange
tests.addTests(suite(Orange))
return tests
|