Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: add a three-state verbosity level : 0, 1, 2 in testmod #31

Merged
merged 2 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions scpdt/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import sys
import os
import inspect
import operator
import contextlib
import doctest
from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, IGNORE_EXCEPTION_DETAIL

Expand Down Expand Up @@ -58,6 +60,22 @@ def find_doctests(module, strategy=None,
return tests



def _map_verbosity(level):
"""A helper for validating the verbosity level."""
if level is None:
level = 0

level = operator.index(level)

if level not in [0, 1, 2]:
raise ValueError("Unknown verbosity setting : level = %s " % level)

dtverbose = True if level == 2 else False

return level, dtverbose


def testmod(m=None, name=None, globs=None, verbose=None,
report=True, optionflags=0, extraglobs=None,
raise_on_error=False, exclude_empty=True,
Expand Down Expand Up @@ -118,6 +136,19 @@ class doctest.Tester, then merges the results into (or creates)
Passing report=0 to testmod is especially useful then, to delay
displaying a summary. Invoke doctest.master.summarize(verbose)
when you're done fiddling.


Parameters
----------
verbose : int
Control verbosity: 0 means only report failures, 1 emit object names,
2 is the max verbosity from doctest. Default is 0.

Returns
-------
a tuple of a DocTestResult, and a dict with details of which objects were examined


"""
# If no module was given, then use __main__.
if m is None:
Expand All @@ -138,26 +169,30 @@ class doctest.Tester, then merges the results into (or creates)
if globs is None:
globs = dict(DEFAULT_NAMESPACE) # NB: copy

verbose, dtverbose = _map_verbosity(verbose)
output = sys.stderr

# Find, parse, and run all tests in the given module.
tests = find_doctests(m, strategy, name, exclude_empty, globs, extraglobs, use_dtfinder)

flags = NORMALIZE_WHITESPACE | ELLIPSIS | IGNORE_EXCEPTION_DETAIL
if raise_on_error:
runner = DebugDTRunner(verbose=verbose, optionflags=flags)
runner = DebugDTRunner(verbose=dtverbose, optionflags=flags)
else:
# our modifications
runner = DTRunner(verbose=verbose, optionflags=flags)
runner = DTRunner(verbose=dtverbose, optionflags=flags)

# our modifications
with mpl(), temp_cwd():
for test in tests:
# XXX print(test.name)
runner.run(test)
if verbose == 1:
output.write(test.name + '\n')
runner.run(test, out=output.write)

if report:
runner.summarize()

return doctest.TestResults(runner.failures, runner.tries)
return doctest.TestResults(runner.failures, runner.tries), runner.get_history()



Expand Down
21 changes: 15 additions & 6 deletions scpdt/_tests/test_testmod.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import io
from contextlib import redirect_stderr

import numpy as np
import pytest
import doctest
Expand All @@ -9,7 +12,7 @@
from .._run import testmod, find_doctests


_VERBOSE = True
_VERBOSE = 2


def test():
Expand All @@ -19,28 +22,28 @@ def test():


def test_module():
res = testmod(module, verbose=_VERBOSE)
res, _ = testmod(module, verbose=_VERBOSE)
if res.failed != 0 or res.attempted == 0:
raise RuntimeError("Test_module(DTFinder) failed)")
return res


def test_module_vanilla_dtfinder():
res = testmod(module, verbose=_VERBOSE, use_dtfinder=False)
res, _ = testmod(module, verbose=_VERBOSE, use_dtfinder=False)
if res.failed != 0 or res.attempted == 0:
raise RuntimeError("Test_module(vanilla DocTestFinder) failed)")
return res


def test_stopwords():
res = testmod(stopwords, verbose=_VERBOSE)
res, _ = testmod(stopwords, verbose=_VERBOSE)
if res.failed != 0 or res.attempted == 0:
raise RuntimeError("Test_stopwords failed.")
return res


def test_public_obj_discovery():
res = testmod(module, verbose=_VERBOSE, strategy='public')
res, _ = testmod(module, verbose=_VERBOSE, strategy='public')
if res.failed != 0 or res.attempted == 0:
raise RuntimeError("Test_public_obj failed.")
return res
Expand All @@ -66,7 +69,7 @@ def test_global_state():
# Make sure doctesting does not alter the global state, as much as reasonable
objs = [module.manip_printoptions]
opts = np.get_printoptions()
testmod(module, verbose=False)
testmod(module)
new_opts = np.get_printoptions()
assert new_opts == opts

Expand All @@ -75,3 +78,9 @@ def test_module_debugrunner():
with pytest.raises((doctest.UnexpectedException, doctest.DocTestFailure)):
res = testmod(failure_cases, raise_on_error=True)


def test_verbosity_1():
# smoke test that verbose=1 works
stream = io.StringIO()
with redirect_stderr(stream):
testmod(failure_cases, verbose=1, report=False)