summaryrefslogtreecommitdiff
path: root/passlib/tests/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'passlib/tests/utils.py')
-rw-r--r--passlib/tests/utils.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py
index d00d30a..9ade9de 100644
--- a/passlib/tests/utils.py
+++ b/passlib/tests/utils.py
@@ -619,6 +619,57 @@ class TestCase(unittest.TestCase):
return value
#===================================================================
+ # subtests
+ #===================================================================
+
+ @contextlib.contextmanager
+ def subTest(self, *args, **kwds):
+ """
+ wrapper for .subTest() which traps SkipTest errors.
+ (see source for details)
+ """
+ # this function works around issue that as 2020-10-08,
+ # .subTest() doesn't play nicely w/ .skipTest();
+ # and also makes it hard to debug which subtest had a failure.
+ # (see https://bugs.python.org/issue25894 and https://bugs.python.org/issue35327)
+ # this method traps skipTest exceptions, and adds some logging to help debug
+ # which subtest caused the issue.
+
+ # setup way to log subtest info
+ # XXX: would like better way to inject messages into test output;
+ # but this at least gets us something for debugging...
+ # NOTE: this hack will miss parent params if called from nested .subTest()
+ def _render_title(_msg=None, **params):
+ out = ("[%s] " % _msg if _msg else "")
+ if params:
+ out += "(%s)" % " ".join("%s=%r" % tuple(item) for item in params.items())
+ return out.strip() or "<subtest>"
+
+ test_log = self.getLogger()
+ title = _render_title(*args, **kwds)
+
+ # run the subtest
+ ctx = super().subTest(*args, **kwds)
+ with ctx:
+ test_log.info("running subtest: %s", title)
+ try:
+ yield
+ except SkipTest:
+ # silence "SkipTest" exceptions, want to keep running next subtest.
+ test_log.info("subtest skipped: %s", title)
+ # XXX: should revisit whether latest py3 version of UTs handle this ok,
+ # meaning it's safe to re-raise this.
+ return
+ except Exception as err:
+ # log unhandled exception occurred
+ # (assuming traceback will be reported up higher, so not bothering here)
+ test_log.warning("subtest failed: %s: %s: %r", title, type(err).__name__, str(err))
+ raise
+
+ # XXX: check for "failed" state in ``self._outcome`` before writing this?
+ test_log.info("subtest passed: %s", title)
+
+ #===================================================================
# other
#===================================================================
_mktemp_queue = None