awaitility icon indicating copy to clipboard operation
awaitility copied to clipboard

Feature Proposal: add an ability to don't throw ConditionTimeoutException

Open Spikhalskiy opened this issue 8 years ago • 17 comments

Hi,

Sometimes we need to wait for something if it gonna happen, but it's fine if it's not. "Wait until a condition is true or timeout is reached" semantic, where reaching a timeout is not an exceptional case.

Example: We have an application that writes logs. These logs are flushed asynchronously and with non-deterministic delay. In our unit test, we want to check the state of the application log, which could be empty and it could be fine. So, we need to wait for 5 seconds, abort waiting if the log became non-empty, or just silently continue execution after this 5 seconds if the log is still empty because it's a normal case.

Now we need to deal with ConditionTimeoutException which will be thrown if the condition is not met after the waiting period, which is ugly and makes the code messy.

Proposal: Add .silent() method to awaitility building chain which disables throwing the exception.

Optional: Add result value to .until() method to make it possible to understand if the condition has been met during waiting without one more explicit check

Spikhalskiy avatar May 27 '16 14:05 Spikhalskiy

Hi,

Doesn't this feature already exists if you use "ignoreException", https://github.com/jayway/awaitility/wiki/Usage#example-9---ignoring-exceptions ?

johanhaleby avatar May 28 '16 11:05 johanhaleby

@johanhaleby No, by tutorial "you can choose to ignore exceptions while evaluating a condition". So, by adding ignoreException you ignore exceptions during condition checking, but don't ignore awaitility own exceptions like ConditionTimeoutException.

Spikhalskiy avatar May 28 '16 16:05 Spikhalskiy

I like this. What if we could provide an onTimeout(callable) that would let use do whatever we please? In my case it would be fail("Some useful message"), so onTimeout(() -> fail("Message")), or you could do onTimeout(() -> return;), etc? If not specified, it keeps the exception?

chedlin avatar Sep 28 '16 19:09 chedlin

Interesting, I like this better than "silent". Wouldn't a variant of Function (the java 8 functional interface) be sufficient for onTimeout? One could then decide to return "null", throw AssertionError or return an arbitrary value.

johanhaleby avatar Sep 29 '16 04:09 johanhaleby

For example there would be no need to do onTimeout(() -> fail("..")), just do onTimeout(ctx -> throw new AssertionError(..)) which will be default behavior. "ctx" contains data that one would need to construct a good error message or to create another type of return value.

johanhaleby avatar Sep 29 '16 04:09 johanhaleby

Would be good to have *) still an easy way to ignore. It would be not very cool to write something like this onTimeout(() -> return;) each time. So, generic onTimeout() + alias for do nothing is the best option for me. *) would be great to have a boolean return value if we don't throw an exception, so we can use awaitility statement directly in a while() for example

Spikhalskiy avatar Sep 29 '16 10:09 Spikhalskiy

I will admit I deal with a lot of legacy code. The variant of Function sounds like a good way to go. ctx would be good.

chedlin avatar Sep 29 '16 16:09 chedlin

this feature would actually be pretty handy for us. our use case is a function that we retry until it stops throwing exceptions. if await() has exhausted the poll duration, we would like to see the exceptions that happened during retries, or at the very least ConditionTimeoutException should have a meaningful getCause(). For example, whether timeout last saw a SQLConnectionException or a different failing assert.

mxk1235 avatar Jun 02 '17 20:06 mxk1235

I think it would be helpful to have a way to specify that Awaitility should throw AssertionError instead of ConditionTimeoutException. It would make using Awaitility much less awkward in cases where we want the test to fail if the timeout is not met.

The onTimeout hook idea is great. Could consider adding a couple of convenience methods as well, e.g. .silent and onTimeoutFail.

The sample tests at https://github.com/awaitility/awaitility/blob/master/awaitility-java8-test/src/test/java/org/awaitility/AwaitilityJava8Test.java are a good example why this would be helpful. Most of them set the timeout through JUnit rather than Awaitility, so they don't have to try-catch-convert-to-AssertionError ConditionTimeoutException. This has the same issue as using e.g. @Test(expected=...) would, namely that you can't set the timeout locally to one condition, you have to set it for the entire test, and if the test fails you don't get useful feedback on the failed condition (e.g. "condition value was x, expected y").

srdo avatar Jun 23 '18 08:06 srdo

Hi guys, Is there any chance that this feature will be implemented? It would be really nice to be able to specify your own callback for timeout with, for example, sensible output to log.

desember avatar Feb 08 '19 08:02 desember

Looks like it's requested by several people so I suppose it's something that we should look into.

On Fri, Feb 8, 2019 at 9:59 AM desember [email protected] wrote:

Hi guys, Is there any chance that this feature will be implemented? It would be really nice to be able to specify your own callback for timeout with, for example, sensible output to log.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/awaitility/awaitility/issues/48#issuecomment-461734418, or mute the thread https://github.com/notifications/unsubscribe-auth/AALalbaDyB6oFOgTDpap0vRL3mUcW5sRks5vLTyMgaJpZM4Ioiej .

johanhaleby avatar Feb 08 '19 12:02 johanhaleby

I've found Awaitility in the context of JUnit tests to be the most salient use-case, so I think natively supporting configuration to throw AssertionError instead of ConditionTimeoutException would be incredibly useful. Supporting .onTimeout might be a generic solution, but I suspect an explicit configuration (i.e. .throwAssertionErrorOnFailure or similar) would be welcome :)

Update - just saw this commit with exactly what I was mentioning! I hope that this work can be finished as this would be a big win!

ngbalk avatar Mar 06 '20 16:03 ngbalk

Hi

Hmmm... the above mentioned commit is from 2018... Any chance to get this into master soon? Would be great!

Regards Oliver

olijaun avatar Apr 27 '20 09:04 olijaun

I'm just working on a case where I need to poll for some time and NOT fail at the end. I'd like to have a custom onTimeout(Supplier) handler :)

vvscher avatar May 18 '21 17:05 vvscher

2 years later...

iklimchuk avatar May 13 '22 14:05 iklimchuk

@iklimchuk I heard they accept contributions

Spikhalskiy avatar May 13 '22 16:05 Spikhalskiy

2023 ... use try catch for that

Shmayro avatar Feb 15 '23 17:02 Shmayro