6
private IWebDriver driver;
private ChildSearchPage currentChild;
private IWebElement divMeetingsTab { get { return driver.FindElement(By.Id("Content_InfantTab1_divMeetings")); } }
private IWebElement btnNewMeeting { get { return driver.FindElement(By.Id("Content_btnNewMeeting")); } }
private DatePicker datePicker { get { return new DatePicker(driver, MeetingDateId); } }
private TimePicker timePicker { get { return new TimePicker(driver, TimePickerId); } }
private IWebElement lblMessage { get { return driver.FindElement(By.Id("LblMessage")); } }
private IWebElement btnMeetingSearch { get { return driver.FindElement(By.Id("Content_btnSearch")); } }
private IWebElement btnEditMeeting { get { return driver.FindElement(By.XPath("/html/body/form/table/tbody/tr[2]/td/table/tbody/tr[2]/td[10]/a/img")); } }
private Utilities util;
private IWebElement btnCreate { get { return driver.FindElement(By.Id("BtnCreateUpdate")); } }
private IWebElement btnAddProvider { get { return driver.FindElement(By.Id("DgTherapists_ctl01_cmdInsert")); } }
private IWebElement txtProviderSearchFirstName { get { return driver.FindElement(By.Id("TxtFirstName")); } }
private IWebElement txtProviderSearchLastName { get { return driver.FindElement(By.Id("TxtLastName")); } }
private IWebElement btnProviderSearch { get { return driver.FindElement(By.Id("BtnSearch")); } }
private IWebElement lnkProviderSearchSelect { get { return driver.FindElement(By.Id("dgProvider_ctl02_HypSelectProvider")); } }
private IWebElement lblProviderName { get { return driver.FindElement(By.Id("DgTherapists_ctl02_Label1")); } }
private IWebElement lblTherapistsName { get { return driver.FindElement(By.CssSelector("html body form#Form1 table.TableContent tbody tr td table#Content_dgPatientMeetingList.Grid tbody tr.GridItemStyle td")); } }
private const String MeetingDateId = "dtcMeetingDate_datePicker";
private const String TimePickerId = "dtcMeetingDate_timePicker";
private const String IFrame = "iframDialog";
private const String InnerHtml = "innerHTML";

public String getProviderNameResults(String FirstName, String LastName, String ProviderFirstName, String ProviderLastName)
{
    util.WaitForPageLoad(driver, 5);
    currentChild.childSearch(FirstName, LastName);
    util.WaitForPageLoad(driver, 5);
    divMeetingsTab.Click();
    util.WaitForPageLoad(driver, 5);

    txtProviderSearchFirstName.SendKeys(ProviderFirstName);
    txtProviderSearchLastName.SendKeys(ProviderLastName);
    btnProviderSearch.Click();
    util.WaitForPageLoad(driver, 5);

    return lblTherapistsName.Text;
}

This is in C#. The properties used are read only properties that I just use driver find element commands to retrieve. My question is why is it that I can't 100% depend on a test to pass because it can't find an element. I am even waiting either 5 seconds or until an element is found.

My hope is that I can trust automated testing with selenium to work efficiently. Any advice would be appreciated. This happens with all of my methods but figured I would use this as an example.

9

WaitForPageLoad() continue's after all the data for the page has been retrieved and I think when the browser OnLoad() function is called. Its possible the browser is still executing JavaScript or processing CSS. Meaning your elements might not be visible on the page just yet.

Instead of waiting for the page to load you should use an explicit wait to wait for the element you want to interact with to be visible. This StackExchange answer shows a C# example of the webdriver wait function: https://stackoverflow.com/a/7312740/1088584

You might only need to wait for the first element of the page to be visible. The other elements prolly will be there and ready. Unless an action changes the view with JavaScript or loads another page. So you could try to limit the usage of the waits until you really need them, but to prevent flickering tests its better just to always wait for the elements.

  • This seems to work the best as the code looks alot better instead of having a wait command after every post back etc. The only issue that resurfaced was a bug related to a RAD Date picker by telerik. – GuardTheGates Jun 4 '15 at 13:43
1

One neat thing you could try is to implement your own wait condition, I don't know the C# bindings, I use it with Java. But maybe you can adapt this to your needs if you think it could help.

For example:

public static ExpectedCondition<Boolean> readyStateComplete(final WebDriver driver) {
    return new ExpectedCondition() {
        public Object apply(Object o) {
            JavascriptExecutor js = (JavascriptExecutor) driver;

            return js.executeScript("document.readyState").equals("complete");
        }

        public String toString() {
            return "Waiting for the document to reach 'complete' status";
        }
    };
}

There is a property in the page document that you can access with javascript called readyState. This readyState property has one of 5 statuses as described here: http://www.w3schools.com/jsref/prop_doc_readystate.asp And you can invoke the above function like:

WebDriverWait wait = new WebDriverWait(driver, 30); // Timeout in seconds
wait.until(readyStateComplete(driver));

The wait.until() method will only return after the ExpectedCondition you pass it returns true. In this case the executed javascript will only return "complete" when the page has completely loaded, meaning, all synchronous and asynchronous javascript will have been completed. For something a bit faster, you can instead use the value "interactive" which is triggered when the DOM is done changing. But not necessarily after javascript has finished executing.

Edit: Depending on if you use something like jquery, the javascript string could be different.

  • This is what we were previously using but it requires us to use the method every time a post back or redirect happens. – GuardTheGates Jun 4 '15 at 13:46
  • That's pretty much what I would expect you to have to do. Webdriver won't wait unless you tell it to exactly when you need it to. If you look at the ExpectedConditions class, there are conditions such as elementToBeClickable() which wait until webdriver acknowledges it can click the element, then returns a reference to that element so you can immediately call .click() on it after. seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… – Julian Jun 4 '15 at 14:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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