Configuration object for asynchronous constructs, such as those provided by traits Eventually and
Waiters.
Configuration object for asynchronous constructs, such as those provided by traits Eventually and
Waiters.
The default values for the parameters are:
| Configuration Parameter | Default Value |
|---|---|
timeout
|
scaled(150 milliseconds)
|
interval
|
scaled(15 milliseconds)
|
the maximum amount of time to wait for an asynchronous operation to complete before giving up and throwing
TestFailedException.
the amount of time to sleep between each check of the status of an asynchronous operation when polling
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
The by-name parameter "succeeds" if it returns a result. It "fails" if it throws any exception that
would normally cause a test to fail. (These are any exceptions except TestPendingException and
Errors listed in the
Treatment of java.lang.Errors section of the
documentation of trait Suite.)
The maximum amount of time in milliseconds to tolerate unsuccessful attempts before giving up is configured by the timeout field of
the PatienceConfig passed implicitly as the last parameter.
The interval to sleep between attempts is configured by the interval field of
the PatienceConfig passed implicitly as the last parameter.
the by-name parameter to repeatedly invoke
the PatienceConfig object containing the timeout and
interval parameters
the result of invoking the fun by-name parameter, the first time it succeeds
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
The by-name parameter "succeeds" if it returns a result. It "fails" if it throws any exception that
would normally cause a test to fail. (These are any exceptions except TestPendingException and
Errors listed in the
Treatment of java.lang.Errors section of the
documentation of trait Suite.)
The maximum amount of time in milliseconds to tolerate unsuccessful attempts before giving up is configured by the timeout field of
the PatienceConfig passed implicitly as the last parameter.
The interval to sleep between attempts is configured by the value contained in the passed
interval parameter.
the Interval configuration parameter
the by-name parameter to repeatedly invoke
the PatienceConfig object containing the (used) timeout and
(unused) interval parameters
the result of invoking the fun by-name parameter, the first time it succeeds
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
The by-name parameter "succeeds" if it returns a result. It "fails" if it throws any exception that
would normally cause a test to fail. (These are any exceptions except TestPendingException and
Errors listed in the
Treatment of java.lang.Errors section of the
documentation of trait Suite.)
The maximum amount of time in milliseconds to tolerate unsuccessful attempts before giving up and throwing
TestFailedException is configured by the value contained in the passed
timeout parameter.
The interval to sleep between attempts is configured by the interval field of
the PatienceConfig passed implicitly as the last parameter.
the Timeout configuration parameter
the by-name parameter to repeatedly invoke
the PatienceConfig object containing the (unused) timeout and
(used) interval parameters
the result of invoking the fun by-name parameter, the first time it succeeds
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
Invokes the passed by-name parameter repeatedly until it either succeeds, or a configured maximum amount of time has passed, sleeping a configured interval between attempts.
The by-name parameter "succeeds" if it returns a result. It "fails" if it throws any exception that
would normally cause a test to fail. (These are any exceptions except TestPendingException and
Errors listed in the
Treatment of java.lang.Errors section of the
documentation of trait Suite.)
The maximum amount of time in milliseconds to tolerate unsuccessful attempts before giving up and throwing
TestFailedException is configured by the value contained in the passed
timeout parameter.
The interval to sleep between attempts is configured by the value contained in the passed
interval parameter.
the Timeout configuration parameter
the Interval configuration parameter
the by-name parameter to repeatedly invoke
the result of invoking the fun by-name parameter, the first time it succeeds
Returns an Interval configuration parameter containing the passed value, which
specifies the amount of time to sleep after a retry.
Returns an Interval configuration parameter containing the passed value, which
specifies the amount of time to sleep after a retry.
Implicit PatienceConfig value providing default configuration values.
Implicit PatienceConfig value providing default configuration values.
To change the default configuration, override or hide this def with another implicit
PatienceConfig containing your desired default configuration values.
Scales the passed Span by the Double factor returned
by spanScaleFactor.
Scales the passed Span by the Double factor returned
by spanScaleFactor.
The Span is scaled by invoking its scaledBy method,
thus this method has the same behavior:
The value returned by spanScaleFactor can be any positive number or zero,
including a fractional number. A number greater than one will scale the Span
up to a larger value. A fractional number will scale it down to a smaller value. A
factor of 1.0 will cause the exact same Span to be returned. A
factor of zero will cause Span.ZeroLength to be returned.
If overflow occurs, Span.Max will be returned. If underflow occurs,
Span.ZeroLength will be returned.
IllegalArgumentException if the value returned from spanScaleFactor
is less than zero
The factor by which the scaled method will scale Spans.
The factor by which the scaled method will scale Spans.
The default implementation of this method will return the span scale factor that
was specified for the run, or 1.0 if no factor was specified. For example, you can specify a span scale factor when invoking ScalaTest
via the command line by passing a -F argument to Runner.
Returns a Timeout configuration parameter containing the passed value, which
specifies the maximum amount to wait for an asynchronous operation to complete.
Returns a Timeout configuration parameter containing the passed value, which
specifies the maximum amount to wait for an asynchronous operation to complete.
Trait that provides the
eventuallyconstruct, which periodically retries executing a passed by-name parameter, until it either succeeds or the configured timeout has been surpassed.The by-name parameter "succeeds" if it returns a result. It "fails" if it throws any exception that would normally cause a test to fail. (These are any exceptions except
TestPendingExceptionandErrors listed in the Treatment ofjava.lang.Errors section of the documentation of traitSuite.)For example, the following invocation of
eventuallywould succeed (not throw an exception):However, because the default timeout is 150 milliseconds, the following invocation of
eventuallywould ultimately produce aTestFailedDueToTimeoutException:Assuming the default configuration parameters, a
timeoutof 150 milliseconds and anintervalof 15 milliseconds, were passed implicitly toeventually, the detail message of the thrownTestFailedDueToTimeoutExceptionwould look like:The code passed to eventually never returned normally. Attempted 2 times over 166.682 milliseconds. Last failure message: 2 was not equal to 110.The cause of the thrown
TestFailedDueToTimeoutExceptionwill be the exception most recently thrown by the block of code passed to eventually. (In the previous example, the cause would be theTestFailedExceptionwith the detail message2 was not equal to 100.)Configuration of
eventuallyThe
eventuallymethods of this trait can be flexibly configured. The two configuration parameters foreventuallyalong with their default values and meanings are described in the following table:timeoutscaled(150 milliseconds)TestFailedDueToTimeoutExceptionintervalscaled(15 milliseconds)The default values of both timeout and interval are passed to the
scaledmethod, inherited fromScaledTimeSpans, so that the defaults can be scaled up or down together with other scaled time spans. See the documentation for traitScaledTimeSpansfor more information.The
eventuallymethods of traitEventuallyeach take aPatienceConfigobject as an implicit parameter. This object provides values for the two configuration parameters. (These configuration parameters are called "patience" because they determine how patient tests will be with asynchronous operations: how long they will tolerate failures before giving up and how long they will wait before checking again after a failure.) TraitEventuallyprovides an implicitvalnamedpatienceConfigwith each configuration parameter set to its default value. If you want to set one or more configuration parameters to a different value for all invocations ofeventuallyin a suite you can override this val (or hide it, for example, if you are importing the members of theEventuallycompanion object rather than mixing in the trait). For example, if you always want the defaulttimeoutto be 2 seconds and the defaultintervalto be 5 milliseconds, you can overridepatienceConfig, like this:Or, hide it by declaring a variable of the same name in whatever scope you want the changed values to be in effect:
Passing your new default values to
scaledis optional, but a good idea because it allows them to be easily scaled if run on a slower or faster system.In addition to taking a
PatienceConfigobject as an implicit parameter, theeventuallymethods of traitEventuallyinclude overloaded forms that take one or twoPatienceConfigParamobjects that you can use to override the values provided by the implicitPatienceConfigfor a singleeventuallyinvocation. For example, if you want to settimeoutto 5 seconds for just one particulareventuallyinvocation, you can do so like this:This invocation of
eventuallywill use 5 seconds for thetimeoutand whatever value is specified by the implicitly passedPatienceConfigobject for theintervalconfiguration parameter. If you want to set both configuration parameters in this way, just list them separated by commas:You can also import or mix in the members of
SpanSugarif you want a more concise DSL for expressing time spans:Note that ScalaTest will not scale any time span that is not explicitly passed to
scaledto make the meaning of the code as obvious as possible. Thus if you ask for "timeout(5 seconds)" you will get exactly that: a timeout of five seconds. If you want such explicitly given values to be scaled, you must pass them toscaleexplicitly like this:The previous code says more clearly that the timeout will be five seconds, unless scaled higher or lower by the
scaledmethod.Simple backoff algorithm
The
eventuallymethods employ a very simple backoff algorithm to try and maximize the speed of tests. If an asynchronous operation completes quickly, a smaller interval will yield a faster test. But if an asynchronous operation takes a while, a small interval will keep the CPU busy repeatedly checking and rechecking a not-ready operation, to some extent taking CPU cycles away from other processes that could proceed. To strike the right balance between these design tradeoffs, theeventuallymethods will check more frequently during the initial interval.Rather than sleeping an entire interval if the initial attempt fails,
eventuallywill only sleep 1/10 of the configured interval. It will continue sleeping only 1/10 of the configured interval until the configured interval has passed, after which it sleeps the configured interval between attempts. Here's an example in which the timeout is set equal to the interval:Even though this call to
eventuallywill time out after only one interval, approximately, the error message will likely report that more than one (and less than ten) attempts were made:The code passed to eventually never returned normally. Attempted 6 times over 100.485 milliseconds. Last failure message: 6 was not equal to 110.Note that if the initial attempt takes longer than the configured interval to complete,
eventuallywill never sleep for a 1/10 interval. You can observe this behavior in the second example above in which the first statement in the block of code passed toeventuallywasThread.sleep(50).Usage note:
Eventuallyintended primarily for integration testingAlthough the default timeouts of trait
Eventuallyare tuned for unit testing, the use ofEventuallyin unit tests is a choice you should question. Usually during unit testing you'll want to mock out subsystems that would requireEventually, such as network services with varying and unpredictable response times. This will allow your unit tests to run as fast as possible while still testing the focused bits of behavior they are designed to test.Nevertheless, because sometimes it will make sense to use
Eventuallyin unit tests (and because it is destined to happen anyway even when it isn't the best choice),Eventuallyby default uses timeouts tuned for unit tests: Calls toeventuallyare more likely to succeed on fast development machines, and if a call does time out, it will do so quickly so the unit tests can move on.When you are using
Eventuallyfor integration testing, therefore, the default timeout and interval may be too small. A good way to override them is by mixing in traitIntegrationPatienceor a similar trait of your own making. Here's an example:Trait
IntegrationPatienceincreases the default timeout from 150 milliseconds to 15 seconds, the default interval from 15 milliseconds to 150 milliseconds. If need be, you can do fine tuning of the timeout and interval by specifying a time span scale factor when you run your tests.