Skip to content

Commit

Permalink
Merge pull request #132 from gabrielfalcao/feature/custom-assertion-msg
Browse files Browse the repository at this point in the history
Add ensure context manager for custom assert messages
  • Loading branch information
timofurrer committed Mar 19, 2017
2 parents 93453c6 + 4ddc280 commit dea6f18
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 2 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

*Nothing to release yet*
### Added
- `ensure` context manager to provide custom assertion messages. Refs #125

## [v1.4.1]
### Added
Expand Down
20 changes: 20 additions & 0 deletions docs/source/api-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -919,3 +919,23 @@ Use the ``chainproperty`` decorator like the following to build your own *chain*
# Build awesome assertion chains
expect(Foo).having.attribute('magic')
Foo.doesnt.implement.attribute('nomagic')
Use custom assertion messages with ``ensure``
---------------------------------------------

With the ``ensure`` context manager *sure* provides an easy to use way to override the ``AssertionError`` message raised by ``sure``'s assertion methods. See the following example:

.. code:: python
import sure
name = myapi.do_something_that_returns_string()
with sure.ensure('the return value actually looks like: {0}', name):
name.should.contain('whatever')
In case ``name`` does not contain the string ``whatever`` it will raise an ``AssertionError`` exception
with the message *the return value actually looks like: <NAME>* (where *<NAME>* would be the actual value of the variable ``name``) instead of *sure*'s default error message in that particular case.

Only ``AssertionError`` exceptions are re-raised by ``sure.ensure()`` with the custom provided message. Every other exception will be ignored and handled as expected.
28 changes: 28 additions & 0 deletions sure/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,34 @@ def chainproperty(func):
return func


class ensure(object):
"""
Contextmanager to ensure that the given assertion message
is printed upon a raised ``AssertionError`` exception.
The ``args`` and ``kwargs`` are used to format
the message using ``format()``.
"""
def __init__(self, msg, *args, **kwargs):
self.msg = msg
self.args = args
self.kwargs = kwargs

def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, traceback):
"""
Catch all ``AsertionError`` exceptions and reraise
them with the message provided to the context manager.
"""
if exc_type is not AssertionError:
return

msg = self.msg.format(*self.args, **self.kwargs)
raise AssertionError(msg)


allows_new_syntax = not os.getenv('SURE_DISABLE_NEW_SYNTAX')


Expand Down
32 changes: 32 additions & 0 deletions tests/test_ensure_ctxmgr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-

import sure


def test_ensure_simple_assertion():
"""Test ensure simple assertion"""

def __test_something():
# same calculated value
name = 'Hodor'
with sure.ensure('the return value actually looks like: {0}', name):
sure.expect(name).should.contain('whatever')


# check if the test function raises the custom AssertionError
sure.expect(__test_something).when.called_with().should.throw(AssertionError, \
'the return value actually looks like: Hodor')


def test_ensure_just_assertion_error():
"""Test that ensure only captures AssertionErrors"""
def __test_something():
# same calculated value
with sure.ensure('neverused'):
raise Exception('This is not an AssertionError')


# check if the test function does not override the original exception
# if it is not an AssertionError exception
sure.expect(__test_something).when.called_with().should.throw(Exception, \
'This is not an AssertionError')

0 comments on commit dea6f18

Please sign in to comment.