summaryrefslogtreecommitdiff
path: root/test/scaffold.py
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2010-03-02 09:35:54 +0000
committer <>2014-12-08 18:37:23 +0000
commit02378192d5bb4b16498d87ace57da425166426bf (patch)
tree2e940dd7284d31c7d32808d9c6635a57547363cb /test/scaffold.py
downloadpython-daemon-02378192d5bb4b16498d87ace57da425166426bf.tar.gz
Imported from /home/lorry/working-area/delta_python-packages_python-daemon/python-daemon-1.5.5.tar.gz.python-daemon-1.5.5
Diffstat (limited to 'test/scaffold.py')
-rw-r--r--test/scaffold.py402
1 files changed, 402 insertions, 0 deletions
diff --git a/test/scaffold.py b/test/scaffold.py
new file mode 100644
index 0000000..566cfb9
--- /dev/null
+++ b/test/scaffold.py
@@ -0,0 +1,402 @@
+# -*- coding: utf-8 -*-
+
+# test/scaffold.py
+# Part of python-daemon, an implementation of PEP 3143.
+#
+# Copyright © 2007–2010 Ben Finney <ben+python@benfinney.id.au>
+# This is free software; you may copy, modify and/or distribute this work
+# under the terms of the GNU General Public License, version 2 or later.
+# No warranty expressed or implied. See the file LICENSE.GPL-2 for details.
+
+""" Scaffolding for unit test modules.
+ """
+
+import unittest
+import doctest
+import logging
+import os
+import sys
+import operator
+import textwrap
+from minimock import (
+ Mock,
+ TraceTracker as MockTracker,
+ mock,
+ restore as mock_restore,
+ )
+
+test_dir = os.path.dirname(os.path.abspath(__file__))
+parent_dir = os.path.dirname(test_dir)
+if not test_dir in sys.path:
+ sys.path.insert(1, test_dir)
+if not parent_dir in sys.path:
+ sys.path.insert(1, parent_dir)
+
+# Disable all but the most critical logging messages
+logging.disable(logging.CRITICAL)
+
+
+def get_python_module_names(file_list, file_suffix='.py'):
+ """ Return a list of module names from a filename list. """
+ module_names = [m[:m.rfind(file_suffix)] for m in file_list
+ if m.endswith(file_suffix)]
+ return module_names
+
+
+def get_test_module_names(module_list, module_prefix='test_'):
+ """ Return the list of module names that qualify as test modules. """
+ module_names = [m for m in module_list
+ if m.startswith(module_prefix)]
+ return module_names
+
+
+def make_suite(path=test_dir):
+ """ Create the test suite for the given path. """
+ loader = unittest.TestLoader()
+ python_module_names = get_python_module_names(os.listdir(path))
+ test_module_names = get_test_module_names(python_module_names)
+ suite = loader.loadTestsFromNames(test_module_names)
+
+ return suite
+
+
+def get_function_signature(func):
+ """ Get the function signature as a mapping of attributes. """
+ arg_count = func.func_code.co_argcount
+ arg_names = func.func_code.co_varnames[:arg_count]
+
+ arg_defaults = {}
+ func_defaults = ()
+ if func.func_defaults is not None:
+ func_defaults = func.func_defaults
+ for (name, value) in zip(arg_names[::-1], func_defaults[::-1]):
+ arg_defaults[name] = value
+
+ signature = {
+ 'name': func.__name__,
+ 'arg_count': arg_count,
+ 'arg_names': arg_names,
+ 'arg_defaults': arg_defaults,
+ }
+
+ non_pos_names = list(func.func_code.co_varnames[arg_count:])
+ COLLECTS_ARBITRARY_POSITIONAL_ARGS = 0x04
+ if func.func_code.co_flags & COLLECTS_ARBITRARY_POSITIONAL_ARGS:
+ signature['var_args'] = non_pos_names.pop(0)
+ COLLECTS_ARBITRARY_KEYWORD_ARGS = 0x08
+ if func.func_code.co_flags & COLLECTS_ARBITRARY_KEYWORD_ARGS:
+ signature['var_kw_args'] = non_pos_names.pop(0)
+
+ return signature
+
+
+def format_function_signature(func):
+ """ Format the function signature as printable text. """
+ signature = get_function_signature(func)
+
+ args_text = []
+ for arg_name in signature['arg_names']:
+ if arg_name in signature['arg_defaults']:
+ arg_default = signature['arg_defaults'][arg_name]
+ arg_text_template = "%(arg_name)s=%(arg_default)r"
+ else:
+ arg_text_template = "%(arg_name)s"
+ args_text.append(arg_text_template % vars())
+ if 'var_args' in signature:
+ args_text.append("*%(var_args)s" % signature)
+ if 'var_kw_args' in signature:
+ args_text.append("**%(var_kw_args)s" % signature)
+ signature_args_text = ", ".join(args_text)
+
+ func_name = signature['name']
+ signature_text = (
+ "%(func_name)s(%(signature_args_text)s)" % vars())
+
+ return signature_text
+
+
+class TestCase(unittest.TestCase):
+ """ Test case behaviour. """
+
+ def failUnlessRaises(self, exc_class, func, *args, **kwargs):
+ """ Fail unless the function call raises the expected exception.
+
+ Fail the test if an instance of the exception class
+ ``exc_class`` is not raised when calling ``func`` with the
+ arguments ``*args`` and ``**kwargs``.
+
+ """
+ try:
+ super(TestCase, self).failUnlessRaises(
+ exc_class, func, *args, **kwargs)
+ except self.failureException:
+ exc_class_name = exc_class.__name__
+ msg = (
+ "Exception %(exc_class_name)s not raised"
+ " for function call:"
+ " func=%(func)r args=%(args)r kwargs=%(kwargs)r"
+ ) % vars()
+ raise self.failureException(msg)
+
+ def failIfIs(self, first, second, msg=None):
+ """ Fail if the two objects are identical.
+
+ Fail the test if ``first`` and ``second`` are identical,
+ as determined by the ``is`` operator.
+
+ """
+ if first is second:
+ if msg is None:
+ msg = "%(first)r is %(second)r" % vars()
+ raise self.failureException(msg)
+
+ def failUnlessIs(self, first, second, msg=None):
+ """ Fail unless the two objects are identical.
+
+ Fail the test unless ``first`` and ``second`` are
+ identical, as determined by the ``is`` operator.
+
+ """
+ if first is not second:
+ if msg is None:
+ msg = "%(first)r is not %(second)r" % vars()
+ raise self.failureException(msg)
+
+ assertIs = failUnlessIs
+ assertNotIs = failIfIs
+
+ def failIfIn(self, first, second, msg=None):
+ """ Fail if the second object is in the first.
+
+ Fail the test if ``first`` contains ``second``, as
+ determined by the ``in`` operator.
+
+ """
+ if second in first:
+ if msg is None:
+ msg = "%(second)r is in %(first)r" % vars()
+ raise self.failureException(msg)
+
+ def failUnlessIn(self, first, second, msg=None):
+ """ Fail unless the second object is in the first.
+
+ Fail the test unless ``first`` contains ``second``, as
+ determined by the ``in`` operator.
+
+ """
+ if second not in first:
+ if msg is None:
+ msg = "%(second)r is not in %(first)r" % vars()
+ raise self.failureException(msg)
+
+ assertIn = failUnlessIn
+ assertNotIn = failIfIn
+
+ def failUnlessOutputCheckerMatch(self, want, got, msg=None):
+ """ Fail unless the specified string matches the expected.
+
+ Fail the test unless ``want`` matches ``got``, as
+ determined by a ``doctest.OutputChecker`` instance. This
+ is not an equality check, but a pattern match according to
+ the ``OutputChecker`` rules.
+
+ """
+ checker = doctest.OutputChecker()
+ want = textwrap.dedent(want)
+ source = ""
+ example = doctest.Example(source, want)
+ got = textwrap.dedent(got)
+ checker_optionflags = reduce(operator.or_, [
+ doctest.ELLIPSIS,
+ ])
+ if not checker.check_output(want, got, checker_optionflags):
+ if msg is None:
+ diff = checker.output_difference(
+ example, got, checker_optionflags)
+ msg = "\n".join([
+ "Output received did not match expected output",
+ "%(diff)s",
+ ]) % vars()
+ raise self.failureException(msg)
+
+ assertOutputCheckerMatch = failUnlessOutputCheckerMatch
+
+ def failUnlessMockCheckerMatch(self, want, tracker=None, msg=None):
+ """ Fail unless the mock tracker matches the wanted output.
+
+ Fail the test unless `want` matches the output tracked by
+ `tracker` (defaults to ``self.mock_tracker``. This is not
+ an equality check, but a pattern match according to the
+ ``minimock.MinimockOutputChecker`` rules.
+
+ """
+ if tracker is None:
+ tracker = self.mock_tracker
+ if not tracker.check(want):
+ if msg is None:
+ diff = tracker.diff(want)
+ msg = "\n".join([
+ "Output received did not match expected output",
+ "%(diff)s",
+ ]) % vars()
+ raise self.failureException(msg)
+
+ def failIfMockCheckerMatch(self, want, tracker=None, msg=None):
+ """ Fail if the mock tracker matches the specified output.
+
+ Fail the test if `want` matches the output tracked by
+ `tracker` (defaults to ``self.mock_tracker``. This is not
+ an equality check, but a pattern match according to the
+ ``minimock.MinimockOutputChecker`` rules.
+
+ """
+ if tracker is None:
+ tracker = self.mock_tracker
+ if tracker.check(want):
+ if msg is None:
+ diff = tracker.diff(want)
+ msg = "\n".join([
+ "Output received matched specified undesired output",
+ "%(diff)s",
+ ]) % vars()
+ raise self.failureException(msg)
+
+ assertMockCheckerMatch = failUnlessMockCheckerMatch
+ assertNotMockCheckerMatch = failIfMockCheckerMatch
+
+ def failIfIsInstance(self, obj, classes, msg=None):
+ """ Fail if the object is an instance of the specified classes.
+
+ Fail the test if the object ``obj`` is an instance of any
+ of ``classes``.
+
+ """
+ if isinstance(obj, classes):
+ if msg is None:
+ msg = (
+ "%(obj)r is an instance of one of %(classes)r"
+ ) % vars()
+ raise self.failureException(msg)
+
+ def failUnlessIsInstance(self, obj, classes, msg=None):
+ """ Fail unless the object is an instance of the specified classes.
+
+ Fail the test unless the object ``obj`` is an instance of
+ any of ``classes``.
+
+ """
+ if not isinstance(obj, classes):
+ if msg is None:
+ msg = (
+ "%(obj)r is not an instance of any of %(classes)r"
+ ) % vars()
+ raise self.failureException(msg)
+
+ assertIsInstance = failUnlessIsInstance
+ assertNotIsInstance = failIfIsInstance
+
+ def failUnlessFunctionInTraceback(self, traceback, function, msg=None):
+ """ Fail if the function is not in the traceback.
+
+ Fail the test if the function ``function`` is not at any
+ of the levels in the traceback object ``traceback``.
+
+ """
+ func_in_traceback = False
+ expect_code = function.func_code
+ current_traceback = traceback
+ while current_traceback is not None:
+ if expect_code is current_traceback.tb_frame.f_code:
+ func_in_traceback = True
+ break
+ current_traceback = current_traceback.tb_next
+
+ if not func_in_traceback:
+ if msg is None:
+ msg = (
+ "Traceback did not lead to original function"
+ " %(function)s"
+ ) % vars()
+ raise self.failureException(msg)
+
+ assertFunctionInTraceback = failUnlessFunctionInTraceback
+
+ def failUnlessFunctionSignatureMatch(self, first, second, msg=None):
+ """ Fail if the function signatures do not match.
+
+ Fail the test if the function signature does not match
+ between the ``first`` function and the ``second``
+ function.
+
+ The function signature includes:
+
+ * function name,
+
+ * count of named parameters,
+
+ * sequence of named parameters,
+
+ * default values of named parameters,
+
+ * collector for arbitrary positional arguments,
+
+ * collector for arbitrary keyword arguments.
+
+ """
+ first_signature = get_function_signature(first)
+ second_signature = get_function_signature(second)
+
+ if first_signature != second_signature:
+ if msg is None:
+ first_signature_text = format_function_signature(first)
+ second_signature_text = format_function_signature(second)
+ msg = (textwrap.dedent("""\
+ Function signatures do not match:
+ %(first_signature)r != %(second_signature)r
+ Expected:
+ %(first_signature_text)s
+ Got:
+ %(second_signature_text)s""")
+ ) % vars()
+ raise self.failureException(msg)
+
+ assertFunctionSignatureMatch = failUnlessFunctionSignatureMatch
+
+
+class Exception_TestCase(TestCase):
+ """ Test cases for exception classes. """
+
+ def __init__(self, *args, **kwargs):
+ """ Set up a new instance """
+ self.valid_exceptions = NotImplemented
+ super(Exception_TestCase, self).__init__(*args, **kwargs)
+
+ def setUp(self):
+ """ Set up test fixtures. """
+ for exc_type, params in self.valid_exceptions.items():
+ args = (None, ) * params['min_args']
+ params['args'] = args
+ instance = exc_type(*args)
+ params['instance'] = instance
+
+ super(Exception_TestCase, self).setUp()
+
+ def test_exception_instance(self):
+ """ Exception instance should be created. """
+ for params in self.valid_exceptions.values():
+ instance = params['instance']
+ self.failIfIs(None, instance)
+
+ def test_exception_types(self):
+ """ Exception instances should match expected types. """
+ for params in self.valid_exceptions.values():
+ instance = params['instance']
+ for match_type in params['types']:
+ match_type_name = match_type.__name__
+ fail_msg = (
+ "%(instance)r is not an instance of"
+ " %(match_type_name)s"
+ ) % vars()
+ self.failUnless(
+ isinstance(instance, match_type),
+ msg=fail_msg)