mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
#!/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):
|
|
"""Optionally 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": [],
|
|
}
|