On 07/20/2015 03:32 AM, Florian Bruhin wrote:
* Ron Adam<ron3...@gmail.com>  [2015-07-19 18:06:22 -0400]:
>
>
>On 07/19/2015 02:33 PM, Florian Bruhin wrote:
> >* Ron Adam<ron3...@gmail.com>   [2015-07-19 11:17:10 -0400]:
> >>>I had to look at the source to figure out what this thread was really all
> >>>about.
>
>And it seems I don't quite get it still, but I am trying.
No worries - I'll try to clarify until things are clear :)

Thanks,  :-)

> >>>Basically it looks to me the purpose of adding "assret" is to add an "alias
> >>>check" for "unsafe" methods.  It doesn't actually add an "alias".  It 
allows
> >>>a developer to use a valid alias to avoid conflicting with methods starting
> >>>with assert that will still work with the mock module.
> >>>
> >>>The mock module says that when "unsafe" flag is set to True, it will not
> >>>raise AssertionError for methods beginning with "assert" and "assret".  It
> >>>doesn't specify what "unsafe" means, and why you would want to do that.
> >>>
> >>>So first do this...
> >>>
> >>>     * Document "unsafe" in mock module.
>
>I still think documenting the purpose of "unsafe", rather than just the
>effect it has is important.
>
> From the confusion in this thread, (including my own), it's clear the
>documentation does need some attention.
>
>
>There are only two places where it mentions "unsafe" in the docs...
>
>The class signature...
>
>"""
>class unittest.mock.Mock(spec=None, side_effect=None, return_value=DEFAULT,
>wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)
>"""
>
>
>And in the section below that.
>
>"""
>unsafe: By default if any attribute starts with assert or assret will raise
>an AttributeError. Passing unsafe=True will allow access to these
>attributes.
>"""
>
>But that doesn't explain the purpose or why these are unsafe or why it
>should throw an AttributeError.   Or what to do with that AttributeError.

It's "unsafe" because tests which:

1) are using the assert_* methods of a mock, and
2) where the programmer did a typo (assert_called() instead of
    assert_called_with() for example)

do silently pass.

And further down, you say...

Compare it with the behavior of a normal object - if you call a method
which doesn't exist, it raises AttributeError.

This isn't possible with Mock objects, as they are designed to support
*any*  call, and you can check the calls have happened after the fact.


And the docs say...

"""
spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.
"""

So calling a method that doesn't exist on a mocked object will raise an AttributeError if it is given a spec.

But if you don't give it a spec, then a mispelling of *any* method will pass silently. So it's not a problem limited to "assert" methods.

It seems the obvious and best solution is to always use a spec.



>It's not clear why getting an AttributeError for methods beginning with
>assert is needed, and how that exception is to be used.   (Should it Bubble
>up, or should it be caught and handled?)

Note the discussion*isn't*  about the fact that assert-methods should
raise AttributeError! The patch also does the same with "assret".

At least if I understand things correctly, the discussion is whether
*only*  "assert*" should be handled as a typo, or "assret*" too.

Both of these are new in 3.5. And they are related to each other. So yes, they do need to be looked at together in order to understand the problem being discussed.

The exception should bubble up, as the whole point of it is to tell
you you did a typo and your test is broken.

I think this is too simple of an explanation. That could be true for any method or attribute call.

>>> m = Mock(spec=["assert_me", "call_me"])
>>> m.call_me()
<Mock name='mock.call_me()' id='140590283081488'>

>>> m.all_me()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
File "/media/hda2/home/ra/Dev/python-dev/python3.5/cpython-master/Lib/unittest/mock.py", line 578, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'all_me'

It does raise AttributeError's on missing methods if a spec is given. So catching mispelled methods in tests is only a problem if you don't use a spec. (And not limited to assert methods)


>>> m.assert_me()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
File "/media/hda2/home/ra/Dev/python-dev/python3.5/cpython-master/Lib/unittest/mock.py", line 583, in __getattr__
    raise AttributeError(name)
AttributeError: assert_me


Why is AttributeError raised here? Why are methods beginning with assert special? (or "unsafe")

Cheers,
   Ron




















_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to