Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selenium tests running too fast, not waiting for the radio button to be selected

I have a Selenium Grid and WebDriver 2.48.2 test that runs too fast. The majority of the time the test stops because a radio button isn't selected prior to a button being pressed.

The radio buttons are setup using JavaScript based on a JSON file to create any number of them within a section on the fly. Once the continue button is clicked that section is destroyed and a new one created with new radio buttons.

I tried an implicit wait with no success.

driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);

The only solution that is working for me is a delay to allow enough time for the radio button to be clicked.

driver.findElement(By.id("radiobuttonid")).click();
Thread.sleep(delay);

But in my opinion this isn't an ideal solution, it's possible the delay may not be long enough or that it's too long, wasting time; there could be any number of radio buttons so the time will increase exponentially.

I've tried setting up various explicit waits with different expected conditions but with no success.

I've tried waiting for the radio button to be created since it may not exist (presenceOfElementLocated & elementToBeClickable). I've tried waiting for it to be selected (elementToBeSelected).

I'm having trouble finding exactly what the expected conditions are supposed to do since the descriptions are brief and open to misinterpretation.

Ideally, I want the test to continue soon after the radio button is clicked. If possible, what's the best way to do this?

EDIT

L.Bar's suggestion below didn't work for me, but it was very helpful to determine that the radio buttons exist, just that the continue button is being clicked before the radio button has a chance to be selected.

EDIT 2

This is just to expand on Jeremiah correct answer. I put the code into a method to make it reusable.

private static Predicate<WebDriver> forceSelectionOfElement (final String id)
{
    return new Predicate<WebDriver>()
    {
        @Override
        public boolean apply(WebDriver arg0)
        {
            WebElement element = arg0.findElement(By.id(id));                
            boolean rval = element.isSelected();

            if (!rval) {
                element.click();
            }

            return rval;
        }
    };
}

Usage

WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(forceSelectionOfElement("q___01_02_01___1___a"));

Remember to import this namespace, it took me an embarrassingly long time to figure out I imported the wrong one :)

import com.google.common.base.Predicate;
like image 379
Pat Avatar asked Oct 14 '15 14:10

Pat


People also ask

How do I make Selenium wait for some time?

Implicit Wait directs the Selenium WebDriver to wait for a certain measure of time before throwing an exception. Once this time is set, WebDriver will wait for the element before the exception occurs. Once the command is in place, Implicit Wait stays in place for the entire duration for which the browser is open.

How do you check a radio button is checked or not in Selenium?

Few of these methods are: isSelected(): Checks whether a radio button is selected or not. isDisplayed(): Checks whether a radion button is displayed on the web page or not. isEnabled(): Checks whether a radion button is enabled or not.


1 Answers

I've had a similar problem, but in my case my 'click' event was lost somewhere. My test would proceed, the click code would trigger, but the state of the element would never visibly change and the test would fail. I ended up leveraging the looping behavior of the WebDriverWait by adding a custom predicate that is a bit more persistent about the selected state.

WebDriverWait wait = new WebDriverWait(driver, 5);
        final By lookup = By.id("radio");
        LOG.debug("Wait for radio to be clickable.");
        wait.until(ExpectedConditions.elementToBeClickable(lookup)); //I assume this implies visibility.
        LOG.debug("Element clickable.  Proceeding into click behavior.");
        wait.until(new Predicate<WebDriver>() {
            @Override
            public boolean apply(WebDriver arg0) {
                LOG.debug("Resolving 'myId' Element");
                WebElement radio = arg0.findElement(lookup);                
                boolean rval = radio.isSelected();
                LOG.debug("Element Resolved and has a state of " + (rval ? "selected" : "not selected"));
                if (!rval) {
                    LOG.debug("Clicking on the Element!");
                    radio.click();
                }
                //If we return false we will loop.  So the first time through we let this click the radio for us.
                //Second time through we should find that the element is clicked.  If it's not we click it again until it represents the state we're wanting.
                return rval;;
            }});

The custom predicate will

  1. Resolve the WebElement
  2. Capture the current Selected status
  3. Click the WebElement if it is not selected
  4. Return the current selected status.

So this should not allow the test to proceed until the clicked state of the element is what I want it to be. So far it's done basically what I've wanted.

It's also worth noting that Thread.sleep is seen as not the best practice for selenium interactions. This is what the ExplicitWait concept is meant to account for. I've linked one of the latest topics in which I'm aware of this being discussed.

Thread.sleep works but implicit wait, webdriverwait and fluent wait does not?

Best of Luck!

like image 98
Jeremiah Avatar answered Oct 14 '22 22:10

Jeremiah