aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Zamarin <arthurzam@gentoo.org>2022-08-27 12:13:42 +0300
committerArthur Zamarin <arthurzam@gentoo.org>2022-08-27 12:13:42 +0300
commitc0472be28724028f2f0860ceb33ce399383461dc (patch)
tree84b0a46ddc2c5932ba9671d3268b79bee11584cc
parentbuild: simplify after cython removal (diff)
downloadsnakeoil-c0472be28724028f2f0860ceb33ce399383461dc.tar.gz
snakeoil-c0472be28724028f2f0860ceb33ce399383461dc.tar.bz2
snakeoil-c0472be28724028f2f0860ceb33ce399383461dc.zip
test: remove TestCase
- final user (pkgcore) has been cleaned - also clean other parts that are unused Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
-rw-r--r--src/snakeoil/test/__init__.py288
-rw-r--r--src/snakeoil/test/mixins.py5
2 files changed, 10 insertions, 283 deletions
diff --git a/src/snakeoil/test/__init__.py b/src/snakeoil/test/__init__.py
index 29bc6246..72ea2b4e 100644
--- a/src/snakeoil/test/__init__.py
+++ b/src/snakeoil/test/__init__.py
@@ -1,28 +1,18 @@
"""Our unittest extensions."""
-__all__ = ('SkipTest', 'TestCase')
-
import os
import random
import string
import subprocess
import sys
-import traceback
-import unittest
-import warnings
-from importlib import import_module
# not relative imports so protect_process() works properly
-from snakeoil import fileutils, klass
-from snakeoil.compatibility import IGNORED_EXCEPTIONS
+from snakeoil import klass
def random_str(length):
"""Return a random string of specified length."""
- if sys.hexversion >= 0x03060000:
- return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
- else:
- return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))
+ return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
def coverage():
@@ -52,266 +42,6 @@ def _os_exit(orig_exit, val):
orig_exit(val)
-def _tryResultCall(result, methodname, *args):
- method = getattr(result, methodname, None)
- if method is not None:
- if methodname != 'addExpectedFailure':
- method(*args)
- return True
- clsmodule = result.__class__.__module__
- if clsmodule == 'unittest' or clsmodule.startswith("unittest."):
- # bugger...
- method(args[0], args[1])
- else:
- method(args[0], str(args[1][1]), args[2])
- return True
- return None
-
-
-class SkipTest(Exception):
- """Raise to skip a test."""
-
-
-def not_a_test(obj):
- """Decorator used to suppress a functor from being treated as a TestCase"""
- obj.__test__ = False
- return obj
-not_a_test = not_a_test(not_a_test)
-
-
-class Todo:
-
- def __init__(self, reason, errors=None):
- self.reason = reason
- self.errors = errors
-
- @classmethod
- def parse(cls, todo):
- if isinstance(todo, str):
- return cls(reason=todo)
- errors, reason = todo
- try:
- errors = list(errors)
- except TypeError:
- errors = [errors]
- return cls(reason=reason, errors=errors)
-
- def expected(self, exception):
- if self.errors is None:
- return True
- for error in self.errors:
- # We want an exact match here.
- if exception is error:
- return True
- return False
-
-
-class TestCase(unittest.TestCase):
-
- """Our additions to the standard TestCase.
-
- This is meant to interact with twisted trial's runner/result objects
- gracefully.
-
- Extra features:
- - Some extra assert* methods.
- - Support "skip" attributes (strings) on both TestCases and methods.
- Such tests do not run at all under "normal" unittest and get a nice
- "skip" message under trial.
- - Support "todo" attributes (strings, tuples of (ExceptionClass, string)
- or tuples of ((ExceptionClass1, ExceptionClass2, ...), string) on both
- TestCases and methods. Such tests are expected to fail instead of pass.
- If they do succeed that is treated as an error under "normal" unittest.
- If they fail they are ignored under "normal" unittest.
- Under trial both expected failure and unexpected success are reported
- specially.
- - Support "suppress" attributes on methods. They should be a sequence of
- (args, kwargs) tuples suitable for passing to
- :py:func:`warnings.filterwarnings`. The method runs with those additions.
- """
-
- def __init__(self, methodName='runTest'):
- # This method exists because unittest.py in python 2.4 stores
- # the methodName as __testMethodName while 2.5 uses
- # _testMethodName.
- self._testMethodName = methodName
- unittest.TestCase.__init__(self, methodName)
-
- def assertLen(self, obj, length, msg=None):
- exp_msg = '%r needs to be len %i, is %i' % (obj, length, len(obj))
- self.assertTrue(len(obj) == length, msg or exp_msg)
-
- assertInstance = klass.alias_method("assertIsInstance")
-
- if not hasattr(unittest.TestCase, 'assertIsInstance'):
- def assertIsInstance(self, obj, kls, msg=None):
- """
- assert that obj is an instance of kls
- """
- exp_msg = '%r needs to be an instance of %r, is %r' % (
- obj, kls, getattr(obj, '__class__', "__class__ wasn't pullable"))
- self.assertTrue(isinstance(obj, kls), msg or exp_msg)
-
- def assertNotInstance(self, obj, kls, msg=None):
- """
- assert that obj is not an instance of kls
- """
- exp_msg = '%r must not be an instance of %r, is %r' % (
- obj, kls, getattr(obj, '__class__', "__class__ wasn't pullable"))
- self.assertFalse(isinstance(obj, kls), msg or exp_msg)
-
- assertIdentical = klass.alias_method("assertIs")
- if not hasattr(unittest.TestCase, 'assertIs'):
- def assertIs(self, this, other, reason=None):
- self.assertTrue(
- this is other, reason or '%r is not %r' % (this, other))
-
- def assertNotIdentical(self, this, other, reason=None):
- self.assertTrue(
- this is not other, reason or '%r is %r' % (this, other))
-
- def assertIn(self, needle, haystack, reason=None):
- self.assertTrue(
- needle in haystack, reason or '%r not in %r' % (needle, haystack))
-
- def assertNotIn(self, needle, haystack, reason=None):
- self.assertTrue(
- needle not in haystack, reason or '%r in %r' % (needle, haystack))
-
- def assertEqual(self, obj1, obj2, msg=None, reflective=True):
- self.assertTrue(obj1 == obj2, msg or '%r != %r' % (obj1, obj2))
- if reflective:
- self.assertTrue(not (obj1 != obj2),
- msg or 'not (%r != %r)' % (obj1, obj2))
-
- def assertNotEqual(self, obj1, obj2, msg=None, reflective=True):
- self.assertTrue(obj1 != obj2, msg or '%r == %r' % (obj1, obj2))
- if reflective:
- self.assertTrue(not (obj1 == obj2),
- msg or 'not (%r == %r)' % (obj1, obj2))
-
- def assertRaises(self, excClass, callableObj, *args, **kwargs):
- try:
- callableObj(*args, **kwargs)
- except excClass:
- return
- except IGNORED_EXCEPTIONS:
- raise
- except Exception as e:
- ex_type, ex, tb = sys.exc_info()
-
- new_exc = AssertionError(
- "expected an exception of %r type from invocation of-\n"
- "%s(*%r, **%r)\n\ninstead, got the following traceback:\n%s" %
- (excClass, callableObj, args, kwargs, traceback.format_exc()))
- new_exc.__cause__ = e
- new_exc.__traceback__ = tb
- raise new_exc
-
- def assertRaisesMsg(self, msg, excClass, callableObj, *args, **kwargs):
- """Fail unless an exception of class excClass is thrown
- by callableObj when invoked with arguments args and keyword
- arguments kwargs. If a different type of exception is
- thrown, it will not be caught, and the test case will be
- deemed to have suffered an error, exactly as for an
- unexpected exception.
- """
- try:
- callableObj(*args, **kwargs)
- except excClass:
- return
- else:
- excName = getattr(excClass, '__name__', str(excClass))
- raise self.failureException("%s not raised: %s" % (excName, msg))
-
- def write_file(self, path, mode, stream, encoding=None):
- return fileutils.write_file(path, mode, stream, encoding=encoding)
-
- # unittest and twisted each have a differing count of how many frames
- # to pop off when displaying an exception; thus we force an extra
- # frame so that trial results are usable
- @staticmethod
- def forced_extra_frame(test):
- test()
-
- def run(self, result=None):
- if result is None:
- result = self.defaultTestResult()
- testMethod = getattr(self, self._testMethodName)
- result.startTest(self)
- try:
- skip = getattr(testMethod, 'skip', getattr(self, 'skip', None))
- todo = getattr(testMethod, 'todo', getattr(self, 'todo', None))
- if todo is not None:
- todo = Todo.parse(todo)
- if skip is not None:
- if not _tryResultCall(result, 'addSkip', self, skip):
- sys.stdout.flush()
- sys.stdout.write("%s: skipping ... " % skip)
- sys.stdout.flush()
- result.addSuccess(self)
- return
-
- try:
- self.setUp()
- except KeyboardInterrupt:
- raise
- except:
- result.addError(self, sys.exc_info())
- return
-
- suppressions = getattr(testMethod, 'suppress', ())
- for args, kwargs in suppressions:
- warnings.filterwarnings(*args, **kwargs)
- addedFilters = warnings.filters[:len(suppressions)]
- ok = False
- try:
- try:
- self.forced_extra_frame(testMethod)
- ok = True
- except self.failureException:
- exc = sys.exc_info()
- if todo is not None and todo.expected(exc[0]):
- _tryResultCall(result, 'addExpectedFailure',
- self, exc, todo)
- else:
- result.addFailure(self, exc)
- except SkipTest as e:
- _tryResultCall(result, 'addSkip', self, str(e))
- except KeyboardInterrupt:
- raise
- except:
- exc = sys.exc_info()
- if todo is not None and todo.expected(exc[0]):
- _tryResultCall(result, 'addExpectedFailure',
- self, exc, todo)
- else:
- result.addError(self, exc)
- # There is a tb in this so do not keep it around.
- del exc
- finally:
- for filterspec in addedFilters:
- if filterspec in warnings.filters:
- warnings.filters.remove(filterspec)
-
- try:
- self.tearDown()
- except KeyboardInterrupt:
- raise
- except:
- result.addError(self, sys.exc_info())
- ok = False
-
- if ok:
- if todo is not None:
- _tryResultCall(result, 'addUnexpectedSuccess', self, todo)
- else:
- result.addSuccess(self)
-
- finally:
- result.stopTest(self)
-
-
_PROTECT_ENV_VAR = "SNAKEOIL_UNITTEST_PROTECT_PROCESS"
@@ -320,26 +50,24 @@ def protect_process(functor, name=None):
if os.environ.get(_PROTECT_ENV_VAR, False):
return functor(self)
if name is None:
- name = "%s.%s.%s" % (self.__class__.__module__, self.__class__.__name__, method_name)
+ name = f"{self.__class__.__module__}.{self.__class__.__name__}.{method_name}"
runner_path = __file__
if runner_path.endswith(".pyc") or runner_path.endswith(".pyo"):
- runner_path = '%s.py' % (runner_path.rsplit(".")[0],)
+ runner_path = runner_path.rsplit(".", maxsplit=1)[0] + ".py"
wipe = _PROTECT_ENV_VAR not in os.environ
try:
os.environ[_PROTECT_ENV_VAR] = "yes"
args = [sys.executable, __file__, name]
p = subprocess.Popen(args, shell=False, env=os.environ.copy(),
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- stdout, _stderr = p.communicate()
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdout, _ = p.communicate()
ret = p.wait()
- assert ret == 0, \
- "subprocess run: %r\nnon zero exit: %s\nstdout:%s\n" % (args, ret, stdout)
+ assert ret == 0, f"subprocess run: {args!r}\nnon zero exit: {ret}\nstdout:\n{stdout}"
finally:
if wipe:
os.environ.pop(_PROTECT_ENV_VAR, None)
- for x in "skip todo __doc__ __name__".split():
+ for x in "__doc__ __name__".split():
if hasattr(functor, x):
setattr(_inner_run, x, getattr(functor, x))
method_name = getattr(functor, '__name__', None)
diff --git a/src/snakeoil/test/mixins.py b/src/snakeoil/test/mixins.py
index 2c8abcad..03360ab9 100644
--- a/src/snakeoil/test/mixins.py
+++ b/src/snakeoil/test/mixins.py
@@ -7,7 +7,6 @@ import sys
import tempfile
from ..compatibility import IGNORED_EXCEPTIONS
-from . import TestCase
def mk_named_tempfile(*args, **kwds):
@@ -80,8 +79,8 @@ class PythonNamespaceWalker:
for x in l:
try:
stats.append((x, os.stat(os.path.join(location, x)).st_mode))
- except OSError as oe:
- if oe.errno != errno.ENOENT:
+ except OSError as exc:
+ if exc.errno != errno.ENOENT:
raise
# file disappeared under our feet... lock file from
# trial can cause this. ignore.