jd / tenacity

Retrying library for Python
http://tenacity.readthedocs.io
Apache License 2.0
6.27k stars 275 forks source link

Disable `wait` for unittest #106

Open DanEEStar opened 6 years ago

DanEEStar commented 6 years ago

I am using the @retry decorator on a function which makes an HTTP-request.

I am using this exact decorator call as an example:

@retry(stop=stop_after_attempt(7), wait=wait_random_exponential(multiplier=1, max=60))
def func():
   ...
   requests.post(...)

I have a unit tests which tests, that func does indeed get called multiple times when the post-request fails.

But it is a bit annoying that the test takes a long time.

Is it possible to disable the wait time somehow only in the unit test to make the test faster? Do I have to mock a specific function?

I also posted this on stackoverflow, in case you want some points :) https://stackoverflow.com/questions/47906671/python-retry-with-tenacity-disable-wait-for-unittest

jd commented 6 years ago

You can change the wait function temporarily in your test:

func.retry.wait = wait_none

Using mock for example, that should be easy to make sure it's then restored to the original.

immerrr commented 6 years ago

@DanEEStar the way I handle time at least in synchronous tests is that I use a datetime-mock library, my preferred one is freezegun but feel free to use any other. The trick is that there's usually a function to advance the frozen clock manually, for freezegun it is

frozen_datetime.tick(delta=datetime.timedelta(seconds=10))

With that in mind I mock time.sleep function not to wait for wallclock time to elapse but rather to advance the frozen clock. This kills two birds with one stone: sleep returns right away and the tests don't get stuck for a long time, but you also get the time invariant back, that is after you invoke time.sleep datetime.now() returns a timestamp in the future. It could be slightly more involved for asynchronous tasks where the time can affect some sort of an event loop, but it's not impossible.

steveb commented 5 years ago

We would also appreciate some specific docs on how to mock out delays in running unit tests. Our current approach just got way more complicated https://review.openstack.org/#/c/596471

josephbosire commented 5 years ago

After working on this for a while I went with func.retry.stop = stop_after_attempt(1)

dvcolgan commented 5 years ago

If anyone finds this now, I dug into @steveb's code and found that in a later pull request it looks like you found an even simpler way of doing this:

https://github.com/openstack/tripleo-common/commit/eba4912fc4cd37442ce4603544bb070612a1df74#diff-f02c888d3d91763350bb6b11c12bf0ffR167

In short, if you decorate a function func with @retry, in the test you can do:

func.retry.sleep = mock.Mock()

And that makes the retry calls happen immediately.

I whipped up a gist that demonstrates Steve's method:

https://gist.github.com/davidscolgan/39433d2de29ea1282bbecaf5afd73900

Gatsby-Lee commented 4 years ago

@davidscolgan Thank you

dtantsur commented 4 years ago

func.retry.sleep = mock.Mock()

Unfortunately, you don't always have an access to the function in a unit test. I'd rather go with the proposal in #228.

richtier commented 2 years ago

I prefer this apporach too @mock.patch("tenacity.nap.time.sleep", MagicMock()) as that will auto-tear down after the test is finished, but monkey patching func.retry.sleep = mock.Mock() does not not tear down the monkey-patch after the test is complete.

skinitimski commented 1 week ago

You can change the wait function temporarily in your test:

func.retry.wait = wait_none

This approach no longer works after https://github.com/jd/tenacity/pull/479. I am instead trying to use the solution enabled by https://github.com/jd/tenacity/pull/236 but not having much luck yet.

robfraz commented 5 days ago

You can change the wait function temporarily in your test:

func.retry.wait = wait_none

This approach no longer works after #479. I am instead trying to use the solution enabled by #236 but not having much luck yet.

Yes, I'm also hitting this problem.