-
Notifications
You must be signed in to change notification settings - Fork 4
Add infrastucture for asserting a series of related values within a single test. #112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# --- BEGIN_HEADER --- | ||
# | ||
# support - helper functions for unit testing | ||
# Copyright (C) 2003-2024 The MiG Project by the Science HPC Center at UCPH | ||
# | ||
# This file is part of MiG. | ||
# | ||
# MiG is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation; either version 2 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# MiG is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
# | ||
# -- END_HEADER --- | ||
# | ||
|
||
"""Infrastruture to support assertion over a range of values. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit-pick: one-line docstrings shouldn't add newline according to PEP8. |
||
""" | ||
|
||
class NoBlockError(AssertionError): | ||
pass | ||
|
||
class NoCasesError(AssertionError): | ||
pass | ||
|
||
class AssertOver: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Classes are slightly ashamed to stand around bare-naked, without even a docstring ;-) |
||
def __init__(self, values=None, testcase=None): | ||
self._attempts = None | ||
self._consulted = False | ||
self._ended = False | ||
self._started = False | ||
self._testcase = testcase | ||
self._values = iter(values) | ||
|
||
def __call__(self, block): | ||
self._attempts = [] | ||
|
||
try: | ||
while True: | ||
block_value = next(self._values) | ||
attempt_info = self._execute_block(block, block_value) | ||
self.record_attempt(attempt_info) | ||
except StopIteration: | ||
pass | ||
|
||
self._ended = True | ||
|
||
def __enter__(self): | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
if self._attempts is None: | ||
raise NoBlockError() | ||
|
||
if len(self._attempts) == 0: | ||
raise NoCasesError() | ||
|
||
if not any(self._attempts): | ||
return True | ||
|
||
value_lines = ["- <%r> : %s" % (attempt[0], str(attempt[1])) for attempt in self._attempts if attempt] | ||
raise AssertionError("assertions raised for the following values:\n%s" % '\n'.join(value_lines)) | ||
|
||
def record_attempt(self, attempt_info): | ||
return self._attempts.append(attempt_info) | ||
|
||
def to_check_callable(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This nested method without direct statements looks a bit strange to me, please at least document it for my sake. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah no, it does return the function call ... but still it would like a docstring. |
||
def raise_unless_consuted(): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll fix this typo during merge and sprinkle in a few missing docstrings. |
||
if not self._consulted: | ||
raise AssertionError("no examiniation made of assertion of multiple values") | ||
return raise_unless_consuted | ||
|
||
def assert_success(self): | ||
self._consulted = True | ||
assert not any(self._attempts) | ||
|
||
@classmethod | ||
def _execute_block(cls, block, block_value): | ||
try: | ||
block.__call__(block_value) | ||
return None | ||
except Exception as blockexc: | ||
return (block_value, blockexc,) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
# | ||
# --- BEGIN_HEADER --- | ||
# | ||
# Copyright (C) 2003-2024 The MiG Project by the Science HPC Center at UCPH | ||
# | ||
# This file is part of MiG. | ||
# | ||
# MiG is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation; either version 2 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# MiG is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
# | ||
# -- END_HEADER --- | ||
# | ||
|
||
"""Configuration related details within the test support library.""" | ||
|
||
from tests.support.loggersupp import FakeLogger | ||
|
||
|
||
class FakeConfiguration: | ||
"""A simple helper to pretend we have a real Configuration object with any | ||
required attributes explicitly passed. | ||
Automatically attaches a FakeLogger instance if no logger is provided in | ||
kwargs. | ||
""" | ||
|
||
def __init__(self, **kwargs): | ||
"""Initialise instance attributes to be any named args provided and a | ||
FakeLogger instance attached if not provided. | ||
""" | ||
self.__dict__.update(kwargs) | ||
if not 'logger' in self.__dict__: | ||
dummy_logger = FakeLogger() | ||
self.__dict__.update({'logger': dummy_logger}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: these should stay to fit existing template. I've left them in when merging.