New submission from Brian McCutchon <bmccutc...@google.com>:
Currently, it is possible to make a basic single-threaded executor for unit testing: class FakeExecutor(futures.Executor): def submit(self, f, *args, **kwargs): future = futures.Future() future.set_result(f(*args, **kwargs)) return future def shutdown(self, wait=True): pass However, this evaluates the provided function eagerly, which may be undesirable for tests. It prevents the tests from catching a whole class of errors (those where the caller forgot to call .result() on a future that is only desirable for its side-effects). It would be great to have an Executor implementation where the function is only called when .result() is called so tests can catch those errors. I might add that, while future.set_result is documented as being supported for unit tests, a comment in the CPython source says that Future.__init__() "Should not be called by clients" (https://github.com/python/cpython/blob/master/Lib/concurrent/futures/_base.py#L317), suggesting that even the above code is unsupported and leaving me wondering how I should test future-heavy code without using mock.patch on everything. ------ Alternatives that don't work ------ One might think it possible to create a FakeFuture to do this: class FakeFuture(object): def __init__(self, to_invoke): self._to_invoke = to_invoke def result(self, timeout=None): return self._to_invoke() However, futures.wait is not happy with this: futures.wait([FakeFuture(lambda x: 1)]) # AttributeError: 'FakeFuture' object has no attribute '_condition' If FakeFuture is made to extend futures.Future, the above line instead hangs: class FakeFuture(futures.Future): def __init__(self, to_invoke): super(FakeFuture, self).__init__() self._to_invoke = to_invoke def result(self, timeout=None): return self._to_invoke() I feel like I shouldn't have to patch out wait() in order to get good unit tests. ---------- messages: 338576 nosy: Brian McCutchon priority: normal severity: normal status: open title: Add deferred single-threaded/fake executor to concurrent.futures type: enhancement versions: Python 3.7 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue36395> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com