proposed check - assert_called_once() is dangerous - warn against its use also assert_called*
Hi; I have a proposal for an additional check that I'm looking for a home for. I wonder if flake8-bugbear would be the right place:
The function assert_called_once() is a new addition to the python unittest.mock module. (see https://docs.python.org/3/library/unittest.mock.html). Unfortunately, a) if you use it against an older version of python it doesn't exist so it makes code not portable. b) if you use it anyway and then backport the code then you typically end up with a test case that passes but doesn't test anything which is nasty and dangerous.
The latter happens whenever a mock without a spec is used and the function is called against it.
mock_object.assert_called_once() # WRONG - doesn't exist in python < 3.6 / mock <
In this case, the function call is mocked so it works. Note also that calls to function names with typos will also .
mock_object.assert_call_once_with(1) # WRONG - typo - this does nothing.
Personally I think it may be a good idea for pycodestyle to warn against any use of mock_object.assert* but it should definitely warn against likely typos.
The proper way to guard against this type of thing is proper TDD style writing of test cases where we ensure they can fail as well as pass. However even that doesn't work in the case of assert_called_once() if you develop against a new version of mock and then test on an old version
This warning might be less needed once all versions of python below 3.6 were obsolete.
- https://engineeringblog.yelp.com/2015/02/assert_called_once-threat-or-menace.html
- https://github.com/python-diamond/Diamond/issues/306
I already discussed this with pycodestyle who don't think it's the kind of check they do. If you think this would be more suitable elsewhere, recommendations also appreciated.
The typo will not work in third-party mock 2.0 and unittest.mock in 3.5+, it will reject unknown assert, assret, etc. methods. You shouldn't be developing new code on Python 3.4, and you should upgrade mock to 2.0 on Python 2.7.
I'd accept a PR against a check like this but don't have cycles to work on it myself. Specifically, it's a pretty tricky check to do given that you'd have to somehow make the linter know:
- that the method is on a mock object
- that the mock library version is too old
This is going to be hard without triggering lots of false positives.
There is already a flake8 plugin focusing on mock's: https://pypi.python.org/pypi/flake8-mock / https://github.com/aleGpereira/flake8-mock
Closing this since Python 3.6 and older are all past their end-of-life dates.