File: test_utils.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (112 lines) | stat: -rw-r--r-- 3,790 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# ===--- test_utils.py ---------------------------------------------------===//
#
#  This source file is part of the Swift.org open source project
#
#  Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
#  Licensed under Apache License v2.0 with Runtime Library Exception
#
#  See https://swift.org/LICENSE.txt for license information
#  See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ===---------------------------------------------------------------------===//
"""
Homegrown unit testing helpers.

The issue is that the unittest.mock was added in Python 3.3 and we need to run
on Python 2.7.

`Stub` and `Mock` are very rudimentary and support only the limited subset of
common unit testing patterns that is used in this project.
"""

import logging
import sys
from contextlib import contextmanager
from io import StringIO


@contextmanager
def captured_output():
    """Capture stdout and stderr and return their output as string buffers."""
    new_out, new_err = StringIO(), StringIO()
    old_out, old_err = sys.stdout, sys.stderr
    try:
        sys.stdout, sys.stderr = new_out, new_err
        yield sys.stdout, sys.stderr
    finally:
        sys.stdout, sys.stderr = old_out, old_err


class Stub:
    """Object literal stub for value objects."""

    def __init__(self, **attributes):
        """All named parameters will create properties on this object."""
        self.__dict__.update(attributes)


class Mock(object):
    """Minimal infrastructure for manually mocking calls to single method.

    Classes inheriting from Mock are expected to create their own mock of the
    tested method with appropriate signature, which appends the call arguments
    as tuple to the `calls` list and returns the canned response retrieved from
    the `respond` dictionary.
    """

    def __init__(self, responses=None):
        """Optionaly initialized with a list of expected calls. See expect."""
        self.calls = []
        self.expected = []
        self.respond = dict()
        responses = responses or []
        for call_args, response in responses:
            self.expect(call_args, response)

    def expect(self, call_args, response):
        """Expect invocation of tested method with given arguments.

        Stores the canned response in the `respond` dictionary.
        """
        call_args = tuple(call_args)
        self.expected.append(call_args)
        self.respond[call_args] = response

    def assert_called_with(self, expected_args):
        """Verify that the tested method was called with provided arguments."""
        expected_args = tuple(expected_args)
        assert expected_args in self.calls, "Expected: {0} in Called: {1}".format(
            expected_args, self.calls
        )

    def assert_called_all_expected(self):
        """Verify that all expected invocations of tested method were called."""
        assert self.calls == self.expected, "\nExpected: {0}, \n  Called: {1}".format(
            self.expected, self.calls
        )


class MockLoggingHandler(logging.Handler):
    """Mock logging handler to check for expected logs."""

    def __init__(self, *args, **kwargs):
        """Prepare the logger for recording messages for each log level."""
        self.reset()
        super(MockLoggingHandler, self).__init__(*args, **kwargs)

    def emit(self, record):
        """Store the message in list for the given log level."""
        self.messages[record.levelname.lower()].append(record.getMessage())

    def reset(self):
        """Clear all log messages."""
        self.messages = {
            "debug": [],
            "info": [],
            "warning": [],
            "error": [],
            "critical": [],
        }