Skip to content
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

Eliminate "during the above exception" in py3 #79

Merged

Conversation

quodlibetor
Copy link
Contributor

This supports Python 2 and Python 3, and dramatically reduces the number of
lines that show up in tracebacks in Python 3.

This supports Python 2 and Python 3, and dramatically reduces the number of
lines that show up in tracebacks in Python 3.
raise AssertionError(*e.args)
err = e
if err is not None:
raise AssertionError(*err.args)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use else: with the try to return and just raise AssertionError in the end then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just remembered that Python 3 (can't find a link now) will delete the exception value caught by as after leaving the except block; that is done to avoiding leaking the frames in the traceback value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blueyed yeah this is constructed this way because if the assertion is raised inside the
except block then you still get the during the above exception message/tb. If the e isn't assigned to some other variable then it is a NameError in py3. If this project didn't support py2 we could theoretically do raise ... from None but that's illegal before py3 and it didn't actually work correctly for me in my testing.

@nicoddemus
Copy link
Member

Thanks @quodlibetor for the PR!

I will merge this and make a new release tomorrow.

@nicoddemus
Copy link
Member

Hi @quodlibetor,

Tried your branch locally:

def test(mocker):
    m = mocker.Mock()
    m('fo')
    m.assert_called_with('')
____________________________________ test _____________________________________

__wrapped_mock_method__ = <function NonCallableMock.assert_called_with at 0x0385CA98>
args = (<Mock id='56891760'>, ''), kwargs = {}, __tracebackhide__ = True
err = None, __mock_self = <Mock id='56891760'>, actual_args = ('fo',)
actual_kwargs = {}, @py_assert2 = ('',), @py_assert1 = False
@py_format4 = "('fo',) == ('',)\n~At index 0 diff: 'fo' != ''\n~Use -v to get the full diff"
@py_format6 = "assert ('fo',) == ('',)\n~At index 0 diff: 'fo' != ''\n~Use -v to get the full diff"

    def assert_wrapper(__wrapped_mock_method__, *args, **kwargs):
        __tracebackhide__ = True
        err = None
        try:
>           __wrapped_mock_method__(*args, **kwargs)

pytest_mock.py:177:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

_mock_self = <Mock id='56891760'>, args = ('',), kwargs = {}
expected = (('',), {})
_error_message = <function NonCallableMock.assert_called_with.<locals>._error_message at 0x0385B2B8>
actual = call('fo'), cause = None

    def assert_called_with(_mock_self, *args, **kwargs):
        """assert that the mock was called with the specified arguments.

            Raises an AssertionError if the args and keyword args passed in are
            different to the last call to the mock."""
        self = _mock_self
        if self.call_args is None:
            expected = self._format_mock_call_signature(args, kwargs)
            raise AssertionError('Expected call: %s\nNot called' % (expected,))

        def _error_message():
            msg = self._format_mock_failure_message(args, kwargs)
            return msg
        expected = self._call_matcher((args, kwargs))
        actual = self._call_matcher(self.call_args)
        if expected != actual:
            cause = expected if isinstance(expected, Exception) else None
>           raise AssertionError(_error_message()) from cause
E           AssertionError: Expected call: mock('')
E           Actual call: mock('fo')

d:\programming\python35\Lib\unittest\mock.py:792: AssertionError

During handling of the above exception, another exception occurred:

mocker = <pytest_mock.MockFixture object at 0x0389B4B0>

    def test(mocker):
        m = mocker.Mock()
        m('fo')
>       m.assert_called_with('')
E       assert ('fo',) == ('',)
E         At index 0 diff: 'fo' != ''
E         Use -v to get the full diff

test_foo.py:6: AssertionError
========================== 1 failed in 0.07 seconds ===========================

So it is missing catching the errors around the internal asserts of assert_wrapper. I will add to your commit fixing this in another PR shortly.

@nicoddemus nicoddemus merged commit 80eb9a1 into pytest-dev:master Mar 30, 2017
@quodlibetor quodlibetor deleted the py3-reduce-assertion-noise branch March 31, 2017 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants