[WIP] bpo-17013: Implement WaitableMock to create Mock objects that can wait until called#12818
[WIP] bpo-17013: Implement WaitableMock to create Mock objects that can wait until called#12818tirkarthi wants to merge 8 commits into
Conversation
wait_until_called and wait_until_called_with are supported. This stores a dictionary with args as key and corresponding event object which is set once there is a call to it. In case of call not present we only want to know if the function was called and hence a per mock event object is also present which is set for no args case.
mariocj89
left a comment
There was a problem hiding this comment.
I think this is going to be really useful!
Sorry, something went wrong.
|
Another problem is that inside import threading
import time
from unittest.mock import WaitableMock, patch, call
def call_after_sometime(func, *args, delay=1):
time.sleep(delay)
func(*args)
def foo(*args):
pass
def bar(*args):
pass
with patch('__main__.foo', WaitableMock(event_class=threading.Event)):
with patch('__main__.bar', WaitableMock(event_class=threading.Event)):
threading.Thread(target=call_after_sometime, args=(foo, 1), kwargs={'delay': 1}).start()
threading.Thread(target=call_after_sometime, args=(bar, 2), kwargs={'delay': 1}).start()
print("bar called with 1 ", bar.wait_until_called_with(2, timeout=2))
print(bar.mock_calls)
bar.assert_called_once_with(2)
print("foo called with 1 ", foo.wait_until_called_with(timeout=2))
print(foo.mock_calls)For foo it would work fine : calls to foo return true and correct call objects. Meanwhile calls to bar with I think there is a flaw that I have added time.sleep in my examples and calls are made misleading me and perhaps the mock object never waits for |
Sorry, something went wrong.
|
Regarding my above comment on irrelevant calls. I got bitten by mock's flexibility :) I was using |
Sorry, something went wrong.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Sorry, something went wrong.
@vstinner This slightly makes the API confusing to me . When I need to check if the mock is called with ('a', 'b') under timeout of 1.0 then I would do Maybe just skip timeout in this case and ask the user to pass timeout to constructor and use it here? But that would mean that
Yes, currently I have used args as the dictionary key there should be a way to have a unique key combination of args and kwargs to store the corresponding event object. |
Sorry, something went wrong.
|
On the PR I am going to open (today ideally), I have block as default as
many other API do.
I am having some issues getting this to work for multiprocessing. I’ll open
it WIP and we can iterate.
…On Fri, 13 Sep 2019 at 12:55, Victor Stinner ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In Lib/unittest/mock.py
<#12818 (comment)>:
> + self._event_class = event_class
+ self._event = event_class()
+ self._expected_calls = defaultdict(event_class)
+
+ def _mock_call(self, *args, **kwargs):
+ ret_value = _safe_super(WaitableMock, self)._mock_call(*args, **kwargs)
+
+ for call in self._mock_mock_calls:
+ event = self._expected_calls[call.args]
+ event.set()
+
+ self._event.set()
+
+ return ret_value
+
+ def wait_until_called(self, timeout=1.0):
IMHO it's a bad idea to hardcode a default timeout. We cannot make
assumption on the hardware performance. Please have a look at
https://bugs.python.org/issue36369 : Python is slow on a Raspberry Pi
Zero W. Does it surprise anyone? Why would Python expect that it's always
run on fast x86-64?
I suggest to either block by default (make the timeout optional) or to
require a timeout value.
In the worst case, please make at least the default configurable.
I spent like 5 years to fix the Python test suite because too many tests
used hardcoded timeouts which fit well for a fast desktop computer, but not
for our slowest buildbot workers. Get a test failure only because the
timeout is too short is annoying.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#12818?email_source=notifications&email_token=AA4JV43VRS5SYCEXU3GF3FTQJN5SVA5CNFSM4HFYN2QKYY3PNVWWK3TUL52HS4DFWFIHK3DMKJSXC5LFON2FEZLWNFSXPKTDN5WW2ZLOORPWSZGOCEVA66Q#discussion_r324157816>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA4JV47OUXKX2ZPJT5U5KQTQJN5SVANCNFSM4HFYN2QA>
.
|
Sorry, something went wrong.
|
Closing in favor of #16094 by Mario. Thanks all for the suggestions on the API. |
Sorry, something went wrong.
This is an initial implementation with preliminary docs and tests to see if it's worthy enough of addition.
Some notes :
mock_calls. I think these should be filtered out or maybe I am doing something wrong.cc : @mariocj89
https://bugs.python.org/issue17013