1

My Webdriver method is not reliable when clicking an 'Item' stored inside a Dropdown Menu?

For example 10 tests will pass but one will fail (Example image listed below)

My Code:

    public void selectTitleFromDropdownMenu(WebElement dropdown, String textToSearchFor) throws Exception {
    Wait<WebDriver> tempWait = new WebDriverWait(this.driver, 30);
    try {
        tempWait.until(ExpectedConditions.elementToBeClickable(dropdown));
        List<WebElement> options = dropdown.findElements(By.tagName("option"));
        Select selectDropdown = new Select(dropdown);
        for (int i = 0; i < options.size(); i++) {
            if (options.get(i).getText().equals(textToSearchFor))
                this.wait.until(ExpectedConditions.visibilityOf(options.get(i)));
                selectDropdown.selectByVisibleText(textToSearchFor);
        }
        System.out.println("Successfully selected the following text: " + textToSearchFor + ", using the following webelement: " + "<" + dropdown.toString() + ">");
        } catch (Exception e) {
            System.out.println("Unable to select the following text: " + textToSearchFor + ", using the following WebElement: " + "<" + dropdown.toString() + ">");
            System.out.println("Exception: " + e.getMessage());
        }
    }

Even the following Code Fails:

    public void selectTitleFromDropdownMenu(WebElement dropdown) throws Exception {
    Wait<WebDriver> tempWait = new WebDriverWait(this.driver, 30);
    try {
        tempWait.until(ExpectedConditions.visibilityOf(dropdown));
        WebElement mySelectElm = dropdown;
        Select mySelect= new Select(mySelectElm);
        mySelect.selectByVisibleText("Mr.");

Element:

<select class="form-control title ng-touched ng-dirty ng-valid-parse ng-valid ng-valid-required" name="Salutation" ng-model="AddingDelivery.EditingDeliveryAddress.Title" ng-options="salut.id as salut.id for salut in Salutations" required="">
<option class="ng-binding" value="">Please select</option>
<option value="0" label="Mr.">Mr.</option>
<option value="1" label="Miss">Miss</option>
<option value="2" label="Mrs.">Mrs.</option>
<option value="3" label="Ms.">Ms.</option>
<option value="4" label="Dr.">Dr.</option>
</select

Example of build Fail: enter image description here

Exceptions: the only exceptions I would see are timeout exceptions, for example unable to locate element after 15Seconds...

thanks for your help

Gbru
  • 1,065
  • 3
  • 24
  • 56
  • It's not reliable because it looks like the drop down is generated using JavaScript. You should use implicit waits and have a reasonable timeout period to make it more reliable. – AntonB Feb 21 '17 at 15:50
  • @AntonB thanks for the adice, would that make much difference if i have already set a explicit wait for this method? – Gbru Feb 21 '17 at 15:52
  • Also, I don't think you need this line: `this.wait.until(ExpectedConditions.visibilityOf(options.get(i)));`, this is basically saying wait for the visibility of the option value... you already waited for the `elementToBeClickable` of the select drop down which is usually more than enough. Also, note that `visibilityOf` option value will fail because option values in html have a height and width of 0. – AntonB Feb 21 '17 at 16:10

2 Answers2

0

If I were you I was going to add some simple retry logic if you don't have something built in your test framework- e.g. retry failed tests a couple of times.

C# example for simple retry code, in Java I guess will be the same:

public void DoWithRetry(Action action, TimeSpan sleepPeriod, int tryCount = 3)
{
    if (tryCount <= 0)
        throw new ArgumentOutOfRangeException(nameof(tryCount));

    while (true) {
        try {
            action();
            break; // success!
        } catch {
            if (--tryCount == 0)
                throw;
            Thread.Sleep(sleepPeriod);
        }
   }
}
Anton Angelov
  • 1,705
  • 13
  • 16
  • `thread.sleep` is an `anti-pattern`, it consumes the thread and should not be used for this case, see: http://stackoverflow.com/questions/8815895/why-is-thread-sleep-so-harmful – AntonB Feb 21 '17 at 15:52
  • 1
    I am aware. Because of that, I said "simple". You can write lots of more optimised code, but I am not sure whether you need it for all cases. If you decompile the WebDriver DLLs you will find lots more so... :) – Anton Angelov Feb 21 '17 at 16:10
0

I would recommend trying the following approach and remove the explicit wait:

 // when you instantiate your driver
 // this is global across all elements, and you no longer need to wait for one element at a time, i.e explicit waits
 driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

 try {
        Select selectDropdown = new Select(dropdown);
        selectDropdown.selectByVisibleText(textToSearchFor);

        System.out.println("Successfully selected the following text: " + textToSearchFor + ", using the following webelement: " + "<" + dropdown.toString() + ">");
        } catch (Exception e) {
            System.out.println("Unable to select the following text: " + textToSearchFor + ", using the following WebElement: " + "<" + dropdown.toString() + ">");
            System.out.println("Exception: " + e.getMessage());
        }
     }
AntonB
  • 2,724
  • 1
  • 31
  • 39