2

I have a working solution, but I am hoping there is a better way.

In automating a website, there are many places where a spinner is shown to tell the user that a process is running. The div is added and removed from the DOM as needed; as opposed to a class change or setting display:none.

When I first starting automating I had a simple wait for the element to no longer be there: numberOfElementsToBe equal to 0. But I kept having timing issues where it took too long for the spinner to appear so the code would assume everything was done, continue on, and fail because the page was not ready yet.

To combat this, I added a try/catch to first look/wait for the spinner to appear for 2 seconds.

try {
        quickWait.until(ExpectedConditions.numberOfElementsToBeMoreThan(By.className(identifier), 0));
    } catch (Exception e) {
        //Nope
    }
    wait.until(ExpectedConditions.numberOfElementsToBe(By.className(identifier), 0));
}

This way, I catch all situations:

  • Normal - Wait for spinner, it shows up normally, then wait for it to go away
  • Slow - Wait for spinner, it takes a second to show up but is still caught by the first wait, and then wait for it to go away
  • Fast - Wait for spinner, but the operation was so fast that the spinner has already come and gone. So the code waits for the spinner for two seconds and doesn't see it, so it falls to the catch which does nothing, and then waits for the spinner to go away (which it already has) so immediately continues on.

All this is fine except for all the "fast" situations. Since the wait fails, it keeps throwing a WARNING in the console log. This makes diagnosing issues a pain as I have to wade through a bunch of warnings trying to find the real issue.

I don't want to turn off all warnings as there could be important info in other areas. So does anyone have any suggestions/alternate methods for handling "wait for situation to exist/wait for it to stop" situations that wouldn't throw out a ton of useless warnings?


UPDATE #1 The timing of the spinner is variable. Sometimes it's so quick it is barely a flicker on the screen, and other times it takes a second to even show on the screen. The tests can not be so brittle that a mistimed spinner causes it to fail. It is only used as a signal that the results are available.

  • The warning happens during runtime, so using @SuppressWarnings() is not an option
  • As stated, I don't want to universally suppress all warnings so "just turning them off" will not work
5
  • Have you tried the solution in: sqa.stackexchange.com/questions/30101/…
    – K-8
    Commented Nov 22, 2017 at 20:13
  • @K-8, the answer is what I had to begin with; wait for the spinner to disappear. But it doesn't take into account the initial waiting for it to appear in the first place. The only error condition that should stop the test is if the spinner lasts longer than the timeout. Other than that, the method should always progress as business as usual.
    – MivaScott
    Commented Nov 22, 2017 at 20:25
  • How come a Warning is logged? Not a Java user, but I don't see anything in the code pointing to a log?
    – FDM
    Commented Nov 27, 2017 at 20:02
  • @FDM I get repeated warnings as the wait.until never finds the element so the WebDriver throws the warning: "WARNING: WebDriverException thrown by findElements(By.cssSelector: h4.modal-title)" as an example
    – MivaScott
    Commented Nov 27, 2017 at 20:20
  • Can't you turn these off? Problem solved. Actual timeouts that are not in a try-catch will fail your test anyway.
    – FDM
    Commented Nov 28, 2017 at 7:00

2 Answers 2

1

I don't really see, why you need to wait for the spinner to appear.

You should have a certain latency in which the spinner element for sure appears.

Therefore my suggestion would be to just wait for this latency time (let's say 200 milliseconds), before you wait for the spinner to disappear (if it's still present).

That way you also test the performance requirement, that the spinner has to always appear within 200 milliseconds (or less).

1

Have you tried changing the default polling time interval (default is 500 milliseconds) to something much shorter to catch those "fast" situations.

import java.util.concurrent.TimeUnit;
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.pollingEvery(100,TimeUnit.MILLISECONDS).until(ExpectedConditions...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.