Source code for contracts.assertion
# Copyright 2017 Benoit Bernard All Rights Reserved.
"""
Module containing code assertions.
It complements the assertions already available in the :class:`~unittest.TestCase` class.
"""
[docs]def does_not_raise(exception_cls, callable_obj, *args, **kwargs):
"""
Asserts that the specified callable object does not raise an exception of the specified class when called.
:param exception_cls: the class of the exception.
:param callable_obj: the callable object (function or method).
:param args: the positional arguments to pass to the callable.
:param kwargs: the keyword arguments to pass to the callable.
:raises: :class:`AssertionError` if the callable raises an exception of the specified class.
"""
try:
callable_obj(*args, **kwargs)
except Exception as e:
# isinstance() checks for any class in the inheritance chain of the specified class.
if isinstance(e, exception_cls):
raise AssertionError("{0} raised by {1}().".format(exception_cls.__name__, callable_obj.__name__))
[docs]def raises(exception_cls, callable_obj, *args, **kwargs):
"""
Asserts that the specified callable object raises an exception of the specified class when called.
Can be used instead of :meth:`~unittest.TestCase.assertRaises` for consistency across unit tests,
especially when :func:`~contracts.assertion.does_not_raise` is also used.
:param exception_cls: the class of the exception.
:param callable_obj: the callable object (function or method).
:param args: the positional arguments to pass to the callable.
:param kwargs: the keyword arguments to pass to the callable.
:raises: :class:`AssertionError` if the callable does not raise an exception of the specified class.
"""
raises_with_msg(exception_cls, callable_obj, None, *args, **kwargs)
[docs]def raises_with_msg(exception_cls, callable_obj, expected_exception_msg, *args, **kwargs):
"""
Asserts that the specified callable object raises an exception of the specified type with the specified message
when called.
:param exception_cls: the class of the exception.
:param callable_obj: the callable object (function or method).
:param expected_exception_msg: the expected substring in the exception's message.
:param args: the positional arguments to pass to the callable.
:param kwargs: the keyword arguments to pass to the callable.
:raises: :class:`AssertionError` if the callable does not raise an exception of the specified class.
"""
has_raised_expected_error = False
try:
callable_obj(*args, **kwargs)
except Exception as e:
# isinstance checks for any class in the inheritance chain of the specified class.
if isinstance(e, exception_cls):
# If a specific error message is expected, we compare it to the error message contained in the exception.
# Otherwise, just having caught the expected exception type is enough.
has_raised_expected_error = expected_exception_msg in str(e) if expected_exception_msg else True
if not has_raised_expected_error:
# Include the expected error message if applicable.
exception_description = exception_cls.__name__ if not expected_exception_msg else "{0} with message '{1}'".format(
exception_cls.__name__, expected_exception_msg)
raise AssertionError("{0} was not raised by {1}().".format(exception_description, callable_obj.__name__))
[docs]def not_called_with(mock_obj, *args, **kwargs):
"""
Asserts that the specified mock object was never called with a specific sequence of arguments.
Acts as a complementary function, because there is no :meth:`assert_not_called_with` method available in the
:class:`~unittest.mock.Mock` class.
:param mock_obj: :class:`~unittest.mock.Mock` object.
:param args: the positional arguments to pass to the callable.
:param kwargs: the keyword arguments to pass to the callable.
:raises: :class:`AssertionError` if the callable does not raise an exception of the specified class.
"""
try:
mock_obj.assert_any_call(*args, **kwargs)
except AssertionError:
# The method was not called with the specified arguments, so everything is good.
return
# The method was called with the specified arguments, so raise an error.
arguments_as_strings = []
if len(args) > 0:
arguments_as_strings.append(", ".join([str(arg) for arg in args]))
if len(kwargs) > 0:
arguments_as_strings.append(", ".join(["{0}={1}".format(key, value) for key, value in kwargs.items()]))
raise AssertionError("Function was unexpectedly called with ({0}).".format(", ".join(arguments_as_strings)))
[docs]def contains_one_element_of_class(obj_cls, iterable_obj):
"""
Asserts that the specified iterable object contains one and only one element of the specified class.
:param obj_cls: the class of the object that is expected to be found in the iterable.
:param iterable_obj: :class:`~collections.abc.Iterable` object.
:raises: :class:`AssertionError` if the callable does not raise an exception of the specified class.
"""
if len(iterable_obj) != 1 or type(iterable_obj[0]) is not obj_cls:
raise AssertionError(
"Iterable should contain one and only one object of class '{0}'.".format(obj_cls.__name__))