DebugClients/Python/coverage/test_helpers.py

changeset 5141
bc64243b7672
parent 5126
d28b92dabc2b
parent 5140
01484c0afbc6
child 5144
1ab536d25072
--- a/DebugClients/Python/coverage/test_helpers.py	Fri Sep 02 19:08:02 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
-
-"""Mixin classes to help make good tests."""
-
-import atexit
-import collections
-import contextlib
-import os
-import random
-import shutil
-import sys
-import tempfile
-import textwrap
-
-from coverage.backunittest import TestCase
-from coverage.backward import StringIO, to_bytes
-
-
-class Tee(object):
-    """A file-like that writes to all the file-likes it has."""
-
-    def __init__(self, *files):
-        """Make a Tee that writes to all the files in `files.`"""
-        self._files = files
-        if hasattr(files[0], "encoding"):
-            self.encoding = files[0].encoding
-
-    def write(self, data):
-        """Write `data` to all the files."""
-        for f in self._files:
-            f.write(data)
-
-    def flush(self):
-        """Flush the data on all the files."""
-        for f in self._files:
-            f.flush()
-
-    if 0:
-        # Use this if you need to use a debugger, though it makes some tests
-        # fail, I'm not sure why...
-        def __getattr__(self, name):
-            return getattr(self._files[0], name)
-
-
-@contextlib.contextmanager
-def change_dir(new_dir):
-    """Change directory, and then change back.
-
-    Use as a context manager, it will give you the new directory, and later
-    restore the old one.
-
-    """
-    old_dir = os.getcwd()
-    os.chdir(new_dir)
-    try:
-        yield os.getcwd()
-    finally:
-        os.chdir(old_dir)
-
-
-@contextlib.contextmanager
-def saved_sys_path():
-    """Save sys.path, and restore it later."""
-    old_syspath = sys.path[:]
-    try:
-        yield
-    finally:
-        sys.path = old_syspath
-
-
-def setup_with_context_manager(testcase, cm):
-    """Use a contextmanager to setUp a test case.
-
-    If you have a context manager you like::
-
-        with ctxmgr(a, b, c) as v:
-            # do something with v
-
-    and you want to have that effect for a test case, call this function from
-    your setUp, and it will start the context manager for your test, and end it
-    when the test is done::
-
-        def setUp(self):
-            self.v = setup_with_context_manager(self, ctxmgr(a, b, c))
-
-        def test_foo(self):
-            # do something with self.v
-
-    """
-    val = cm.__enter__()
-    testcase.addCleanup(cm.__exit__, None, None, None)
-    return val
-
-
-class ModuleAwareMixin(TestCase):
-    """A test case mixin that isolates changes to sys.modules."""
-
-    def setUp(self):
-        super(ModuleAwareMixin, self).setUp()
-
-        # Record sys.modules here so we can restore it in cleanup_modules.
-        self.old_modules = list(sys.modules)
-        self.addCleanup(self.cleanup_modules)
-
-    def cleanup_modules(self):
-        """Remove any new modules imported during the test run.
-
-        This lets us import the same source files for more than one test.
-
-        """
-        for m in [m for m in sys.modules if m not in self.old_modules]:
-            del sys.modules[m]
-
-
-class SysPathAwareMixin(TestCase):
-    """A test case mixin that isolates changes to sys.path."""
-
-    def setUp(self):
-        super(SysPathAwareMixin, self).setUp()
-        setup_with_context_manager(self, saved_sys_path())
-
-
-class EnvironmentAwareMixin(TestCase):
-    """A test case mixin that isolates changes to the environment."""
-
-    def setUp(self):
-        super(EnvironmentAwareMixin, self).setUp()
-
-        # Record environment variables that we changed with set_environ.
-        self.environ_undos = {}
-
-        self.addCleanup(self.cleanup_environ)
-
-    def set_environ(self, name, value):
-        """Set an environment variable `name` to be `value`.
-
-        The environment variable is set, and record is kept that it was set,
-        so that `cleanup_environ` can restore its original value.
-
-        """
-        if name not in self.environ_undos:
-            self.environ_undos[name] = os.environ.get(name)
-        os.environ[name] = value
-
-    def cleanup_environ(self):
-        """Undo all the changes made by `set_environ`."""
-        for name, value in self.environ_undos.items():
-            if value is None:
-                del os.environ[name]
-            else:
-                os.environ[name] = value
-
-
-class StdStreamCapturingMixin(TestCase):
-    """A test case mixin that captures stdout and stderr."""
-
-    def setUp(self):
-        super(StdStreamCapturingMixin, self).setUp()
-
-        # Capture stdout and stderr so we can examine them in tests.
-        # nose keeps stdout from littering the screen, so we can safely Tee it,
-        # but it doesn't capture stderr, so we don't want to Tee stderr to the
-        # real stderr, since it will interfere with our nice field of dots.
-        old_stdout = sys.stdout
-        self.captured_stdout = StringIO()
-        sys.stdout = Tee(sys.stdout, self.captured_stdout)
-
-        old_stderr = sys.stderr
-        self.captured_stderr = StringIO()
-        sys.stderr = self.captured_stderr
-
-        self.addCleanup(self.cleanup_std_streams, old_stdout, old_stderr)
-
-    def cleanup_std_streams(self, old_stdout, old_stderr):
-        """Restore stdout and stderr."""
-        sys.stdout = old_stdout
-        sys.stderr = old_stderr
-
-    def stdout(self):
-        """Return the data written to stdout during the test."""
-        return self.captured_stdout.getvalue()
-
-    def stderr(self):
-        """Return the data written to stderr during the test."""
-        return self.captured_stderr.getvalue()
-
-
-class DelayedAssertionMixin(TestCase):
-    """A test case mixin that provides a `delayed_assertions` context manager.
-
-    Use it like this::
-
-        with self.delayed_assertions():
-            self.assertEqual(x, y)
-            self.assertEqual(z, w)
-
-    All of the assertions will run.  The failures will be displayed at the end
-    of the with-statement.
-
-    NOTE: this only works with some assertions.  These are known to work:
-
-        - `assertEqual(str, str)`
-
-        - `assertMultilineEqual(str, str)`
-
-    """
-    def __init__(self, *args, **kwargs):
-        super(DelayedAssertionMixin, self).__init__(*args, **kwargs)
-        # This mixin only works with assert methods that call `self.fail`.  In
-        # Python 2.7, `assertEqual` didn't, but we can do what Python 3 does,
-        # and use `assertMultiLineEqual` for comparing strings.
-        self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
-        self._delayed_assertions = None
-
-    @contextlib.contextmanager
-    def delayed_assertions(self):
-        """The context manager: assert that we didn't collect any assertions."""
-        self._delayed_assertions = []
-        old_fail = self.fail
-        self.fail = self._delayed_fail
-        try:
-            yield
-        finally:
-            self.fail = old_fail
-        if self._delayed_assertions:
-            if len(self._delayed_assertions) == 1:
-                self.fail(self._delayed_assertions[0])
-            else:
-                self.fail(
-                    "{0} failed assertions:\n{1}".format(
-                        len(self._delayed_assertions),
-                        "\n".join(self._delayed_assertions),
-                    )
-                )
-
-    def _delayed_fail(self, msg=None):
-        """The stand-in for TestCase.fail during delayed_assertions."""
-        self._delayed_assertions.append(msg)
-
-
-class TempDirMixin(SysPathAwareMixin, ModuleAwareMixin, TestCase):
-    """A test case mixin that creates a temp directory and files in it.
-
-    Includes SysPathAwareMixin and ModuleAwareMixin, because making and using
-    temp directories like this will also need that kind of isolation.
-
-    """
-
-    # Our own setting: most of these tests run in their own temp directory.
-    # Set this to False in your subclass if you don't want a temp directory
-    # created.
-    run_in_temp_dir = True
-
-    # Set this if you aren't creating any files with make_file, but still want
-    # the temp directory.  This will stop the test behavior checker from
-    # complaining.
-    no_files_in_temp_dir = False
-
-    def setUp(self):
-        super(TempDirMixin, self).setUp()
-
-        if self.run_in_temp_dir:
-            # Create a temporary directory.
-            self.temp_dir = self.make_temp_dir("test_cover")
-            self.chdir(self.temp_dir)
-
-            # Modules should be importable from this temp directory.  We don't
-            # use '' because we make lots of different temp directories and
-            # nose's caching importer can get confused.  The full path prevents
-            # problems.
-            sys.path.insert(0, os.getcwd())
-
-        class_behavior = self.class_behavior()
-        class_behavior.tests += 1
-        class_behavior.temp_dir = self.run_in_temp_dir
-        class_behavior.no_files_ok = self.no_files_in_temp_dir
-
-        self.addCleanup(self.check_behavior)
-
-    def make_temp_dir(self, slug="test_cover"):
-        """Make a temp directory that is cleaned up when the test is done."""
-        name = "%s_%08d" % (slug, random.randint(0, 99999999))
-        temp_dir = os.path.join(tempfile.gettempdir(), name)
-        os.makedirs(temp_dir)
-        self.addCleanup(shutil.rmtree, temp_dir)
-        return temp_dir
-
-    def chdir(self, new_dir):
-        """Change directory, and change back when the test is done."""
-        old_dir = os.getcwd()
-        os.chdir(new_dir)
-        self.addCleanup(os.chdir, old_dir)
-
-    def check_behavior(self):
-        """Check that we did the right things."""
-
-        class_behavior = self.class_behavior()
-        if class_behavior.test_method_made_any_files:
-            class_behavior.tests_making_files += 1
-
-    def make_file(self, filename, text="", newline=None):
-        """Create a file for testing.
-
-        `filename` is the relative path to the file, including directories if
-        desired, which will be created if need be.
-
-        `text` is the content to create in the file, a native string (bytes in
-        Python 2, unicode in Python 3).
-
-        If `newline` is provided, it is a string that will be used as the line
-        endings in the created file, otherwise the line endings are as provided
-        in `text`.
-
-        Returns `filename`.
-
-        """
-        # Tests that call `make_file` should be run in a temp environment.
-        assert self.run_in_temp_dir
-        self.class_behavior().test_method_made_any_files = True
-
-        text = textwrap.dedent(text)
-        if newline:
-            text = text.replace("\n", newline)
-
-        # Make sure the directories are available.
-        dirs, _ = os.path.split(filename)
-        if dirs and not os.path.exists(dirs):
-            os.makedirs(dirs)
-
-        # Create the file.
-        with open(filename, 'wb') as f:
-            f.write(to_bytes(text))
-
-        return filename
-
-    # We run some tests in temporary directories, because they may need to make
-    # files for the tests. But this is expensive, so we can change per-class
-    # whether a temp directory is used or not.  It's easy to forget to set that
-    # option properly, so we track information about what the tests did, and
-    # then report at the end of the process on test classes that were set
-    # wrong.
-
-    class ClassBehavior(object):
-        """A value object to store per-class."""
-        def __init__(self):
-            self.tests = 0
-            self.skipped = 0
-            self.temp_dir = True
-            self.no_files_ok = False
-            self.tests_making_files = 0
-            self.test_method_made_any_files = False
-
-    # Map from class to info about how it ran.
-    class_behaviors = collections.defaultdict(ClassBehavior)
-
-    @classmethod
-    def report_on_class_behavior(cls):
-        """Called at process exit to report on class behavior."""
-        for test_class, behavior in cls.class_behaviors.items():
-            bad = ""
-            if behavior.tests <= behavior.skipped:
-                bad = ""
-            elif behavior.temp_dir and behavior.tests_making_files == 0:
-                if not behavior.no_files_ok:
-                    bad = "Inefficient"
-            elif not behavior.temp_dir and behavior.tests_making_files > 0:
-                bad = "Unsafe"
-
-            if bad:
-                if behavior.temp_dir:
-                    where = "in a temp directory"
-                else:
-                    where = "without a temp directory"
-                print(
-                    "%s: %s ran %d tests, %d made files %s" % (
-                        bad,
-                        test_class.__name__,
-                        behavior.tests,
-                        behavior.tests_making_files,
-                        where,
-                    )
-                )
-
-    def class_behavior(self):
-        """Get the ClassBehavior instance for this test."""
-        return self.class_behaviors[self.__class__]
-
-# When the process ends, find out about bad classes.
-atexit.register(TempDirMixin.report_on_class_behavior)
-
-#
-# eflag: FileType = Python2

eric ide

mercurial