From d1c45f77285b80ce893e707ae8c371302479802f Mon Sep 17 00:00:00 2001 From: Evgeni Burovski Date: Fri, 3 Jun 2022 09:50:42 +0300 Subject: [PATCH] ENH: add a three-state verbosity level : 0, 1, 2 in testmod 0 is failures only; 1 is emit object names just before doctesting; 2 is full, emit all examples. --- scpdt/_run.py | 31 +++++++++++++++++++++++++++---- scpdt/_tests/test_testmod.py | 13 +++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/scpdt/_run.py b/scpdt/_run.py index 01c692c..5ed28f8 100644 --- a/scpdt/_run.py +++ b/scpdt/_run.py @@ -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 @@ -118,6 +120,14 @@ 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. + """ # If no module was given, then use __main__. if m is None: @@ -138,21 +148,34 @@ class doctest.Tester, then merges the results into (or creates) if globs is None: globs = dict(DEFAULT_NAMESPACE) # NB: copy + if verbose is None: + verbose = 0 + verbose = operator.index(verbose) + if verbose < 0 or verbose > 2: + raise ValueError("unknown verbose setting : %s " % verbose) + if verbose < 2: + dtverbose = False + else: + dtverbose = True + + 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() diff --git a/scpdt/_tests/test_testmod.py b/scpdt/_tests/test_testmod.py index a5cc1b8..60a67f4 100644 --- a/scpdt/_tests/test_testmod.py +++ b/scpdt/_tests/test_testmod.py @@ -1,3 +1,6 @@ +import io +from contextlib import redirect_stderr + import numpy as np import pytest import doctest @@ -9,7 +12,7 @@ from .._run import testmod, find_doctests -_VERBOSE = True +_VERBOSE = 2 def test(): @@ -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 @@ -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)