Selenium FindElements() times out. Get around unpredictable loading icons - c#

I've searched quite a bit on this topic on the stack and other places.
When I run driver.FindElements(By.myselector) my browser waits 60 seconds to time out. Instead of returning an empty list as described by the documentation
( https://www.selenium.dev/documentation/en/getting_started_with_webdriver/locating_elements/ ). It seems to be a great solution to work around an element possibly being in the DOM.
I need to check for the possible existence of loading icons/gifs. When the icons are present I need to wait until they are gone. When the icons are not there I need the method to fail to find MUCH faster than 60 seconds so I can let the script continue to test. The loading icon's appearance is not always predictable.
Is there a way to
Make an individual operation fail quickly?
Get FindElements() to return an empty list instead of failing after 60 seconds?
Get around unpredictable DOM blocking loading icons another way?
Examples of code I have tried:
Find if any elements are returned. Originally had a loop to keep checking if empty. If not Thread.Sleep() then reassign and check for existence again. Waits 60 seconds to fail.
public static IWebElement FindElementIfExists(ChromeDriver _driver, By by)
{
ReadOnlyCollection<IWebElement> elements = _driver.FindElements(by);
return (elements.Count >= 1) ? elements[0] : null;
}
This code works when the loading icon shows up, but Selenium waits 60 seconds and fails on
OpenQA.Selenium.WebDriverException: 'The HTTP request to the remote WebDriver server for URL timeout after 60 seconds when the icon is
not in the DOM.
public static bool isElementDisplayed(ChromeDriver _driver, By aSelector)
{
try
{
// WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(4));
wait.Until(ExpectedConditions.ElementIsVisible(aSelector));
return _driver.FindElement(aSelector).Displayed;
}
catch (Exception ex)
{
if (ex is NoSuchElementException || ex is StaleElementReferenceException || ex is TimeoutException)
{
return false;
}
else
{
throw ex;
}
}
}
public static void WaitForElementToBeGone(ChromeDriver _driver, By aSelector, int timeout)
{
if (isElementDisplayed(_driver, aSelector))
{
new WebDriverWait(_driver, TimeSpan.FromSeconds(timeout)).Until(ExpectedConditions.StalenessOf(_driver.FindElement(aSelector)));
}
}
Thanks again

Related

SBNotificationHub.RegisterNativeAsync fails to return

When calling SBNotificationHub.RegisterNativeAsync, sometimes it succeeds just fine, the registration is created, and notifications can be received. At other times, the callback of the method is never hit, and no registration is created. I added a timer to give some feedback on when this occurs. Since the callback is never called, I'm finding this difficult to debug.
The UnregisterAllAsync always completes successfully, and enters the callback.
This failure does not occur randomly. Specifically, when calling this for the initial registration on starting the app, it succeeds, when changing tags upon logout, it succeeds, when changing tags upon login, it fails. All of these use the same code, the only difference is the tags. I suspected the tags may be the culprit, but changing to a constant set of tags for all calls to this code did not change this behavior at all. I tried retrying the registration after 5 seconds (thus the timer) if there was no response, but that just results in the same failure every 5 seconds.
Similar behavior, by the way, when awaiting RegisterNativeAsyncAsync. The next line just never gets hit.
Hub.UnregisterAllAsync(DeviceToken, (error) =>
{
if (error != null)
{
Console.WriteLine("Error calling Unregister: {0}", error.ToString());
return;
}
bool callbackReached = false;
Hub.RegisterNativeAsync(DeviceToken, tags, (errorCallback) =>
{
callbackReached = true;
if (errorCallback != null)
Console.WriteLine("RegisterNativeAsync error: " + errorCallback.ToString());
else
Console.WriteLine("RegisterNativeAsync succeeded.");
});
new Timer((Object obj) =>
{
if (!callbackReached)
{
Console.WriteLine("RegisterNativeAsync failed to return after 5 seconds.");
}
},
null,
5000,
0);
});
A solution would be great, of course, but just some more information about why the registration is failing, to give me some information to go on while debugging this, would be immensely helpful.

Exception: "Timed Out After xx seconds" on wait.until Selenium WebDriver C#

I'm trying to figure out how it's possible to wait for a condition in order to login into a web page with Selenium Driver. However it is not as straightforward as it may seem. I'm working around with Thread.Sleep(3000); but I'm sure there should be a better solution. So, my code works as follows:
Load page with firefox driver.
Execute a javascript snnipet to change language (I need to wait for this in order to login).
IJavaScriptExecutor executor = (IJavaScriptExecutor)firefox;
executor.ExecuteScript("arguments[0].click();", idioma_español);
Above instruction leads to a page reload.
Next instruction is intented to wait for page to be reloaded
WebDriverWait wait = new WebDriverWait(newDriver,TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.TextToBePresentInElementValue(element,textToAppear));
Continue to login.
However, when I run the code, it throws the following exception:
Looking closer into de output, I found this:
I tried with different expected conditions such as: TextToBePresentInElement,ElementExists; but it throws the same exception.
I also tried with ExecuteAsyncScript("arguments[0].click();", idioma_español); method, but it throws "Document was unloaded " exception.
It looks like the text element has been replaced, so the element was stale. I think you can solve it by fetch the new element every time. See code below:
public bool WaitForTextToAppear(IWebDriver driver, By elementLocator, string textToAppear, int timeoutInSec=10)
{
IWait<IWebDriver> wait = new DefaultWait<IWebDriver>(driver);
wait.Timeout = TimeSpan.FromSeconds(timeoutInSec);
wait.PollingInterval = TimeSpan.FromMilliseconds(300);
try
{
wait.Until(d => IsTextPresentedIn(d, elementLocator, textToAppear));
return true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Error: " + ex.Message);
return false;
}
}
private bool IsTextPresentedIn(IWebDriver driver, By elementLocator, string textToAppear)
{
try
{
var elements = driver.FindElements(elementLocator);
if (elements.Count>0 && elements[0].Text.Equals(textToAppear, StringComparison.OrdinalIgnoreCase))
return true;
}
catch
{
return false;
}
return false;
}
// using the web driver extension.
bool textAppeared = WaitForTextToAppear(driver, By.CssSelector("selector-of-the-text-element"), "HERE IS THE EXPECTED TEXT");

Windows service with SQL Loop throwing unhandled exception

I'm new to c# working with a windows service which has a timer but the autoreset is set to false so it supposed to run an infinite loop Querying to a Sql database. If the SQL returns records the process runs fine, but when no records are found the service throws an exception after 10 - 12 minutes, System.StackOverflowException was unhandled which is not clear (to me). Not sure how to better capture the issue or how to correct. Any assistance would be apprecieated.
`private static bool LoadRequests()
{
// check for requests will return combined Header/Detail record
bool RequestsLoaded = false;
string XMLURL = "";
string currentWorkingDirectory = "";
string text = "";
int rowcounter = 0;
try
{
//Summary List will be a subset of requested items, by ID#
var SummaryInfoList = new List<SummaryInfo>();
ReqHdrPlusDtlList myReqHdrPlusDetailList = new ReqHdrPlusDtlList();
List<ReqHdrPlusDtl> myReqHdrPlusDetailList = myReqHdrPlusDetailList.GetReqHdrPlusDtlList();
if (myReqHdrPlusDetailList != null && myReqHdrPlusDetailList.Count > 0)
{
// set check for last record
ReqHdrPlusDtl last = myReqHdrPlusDetailList.Last();
// scroll through each record in Request List
foreach (ReqHdrPlusDtl detailrec in myReqHdrPlusDetailList)
{
/// process id records ...
/// ...
} // exit for/each
}
else
{
//no records in list sleep for half a second before proceeding
Thread.Sleep(500);
text = "Done sleeping...";
WriteToAppLog(text);
}
//As soon as one request is fully processed, get the next pending record.
LoadRequests();
} // ends try
catch (Exception e)
{
WriteErrorMessageToAppLog(e);
RequestsLoaded = false;
}
return RequestsLoaded;
}`
When you look for the exception in the docs it states the following.
The exception that is thrown when the execution stack overflows because it contains too many nested method calls.
This exception often happens when you have an infinite loop, like in your code.
You are working with recursion (Recursion is an important programming technique that causes a function to call itself, source).
Because you keep calling your own function over and over again, you keep building up the stack, until it overflows.
You should rewrite the function so that it will actually end.
I suggest using a DispatcherTimer to call your function every 500ms, instead of Thread.Sleep() because Thread.Sleep() also blocks any execution of code on that thread.
private DispatcherTimer _dispatcherTimer;
private void SetUpTimer(){
_dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
_dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
_dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
LoadRequests();
}
Note: I didn't test the code, and I haven't written c# in a while, though it should help you get there
You are using a recursive call which is causing the stack overflow problem. Get rid of the recursive call to correct. Possibly make a control loop as follows:
bool success = true;
while(success)
{
try
{
LoadRequests();
Thread.Sleep(500);
}
catch (exception ex)
{
//Log Error ex.Message;
success = false;
}
}
Once you eliminate calling the function inside of itself, the stack overflow problem should be resolved.
Edit
One other comment, is the recursion is never-ending (no control statement to block execution) which is a big no-no. If you have to use recursion then there must be a way to exit the method (a stop condition). All that being said, almost every recursive problem can be solved iteratively and it can be very beneficial to do so, as it consumes significantly less system resources. The above listed code would be an iterative solution.

.NET Selenium NoSuchElementException; WebDriverWait.Until() doesn't work

We have a .NET 4.5, MVC, C# project. We're using Selenium for UI tests, and the tests keep intermittently failing on lines that we have wait.Until(). One such example is:
NoSuchElementException was unhandled by user code
An exception of type 'OpenQA.Selenium.NoSuchElementException' occurred in WebDriver.dll but was not handled in user code
Additional information: Unable to locate element: {"method":"css selector","selector":"#assessment-472 .status-PushedToSEAS"}
It's thrown right here:
Thread.Sleep(600);
wait.Until(drv => drv.FindElement(By.CssSelector("#" + assessmentQueueId + " .status-PushedToSEAS")));
I can see that the browser opens, I see it get to that point, and I can inspect element to see that the element exists. Its id is exactly correct.
We have this problem A LOT and so far the solution has been to throw Thread.Sleep(600) (or some similar time) in front of it. The whole point of wait.Until() is to not have to do that, and this is making our test suites get very long. Also, as you can see in the example above, sometimes we have the problem even after putting a Thread.Sleep() in front of it and we have to extend the time.
Why is .NET Selenium's WebDriver.Until() not working, and is there a different way to do the same thing without just waiting a set period of time? Again, the problem is intermittent, meaning that it only happens sometimes, and it could happen at any number of wait.Until() statements, not just the one shown!
Edit:
This is a class variable.
private WebDriverWait wait;
It is instantiated like this:
this.wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
I decided to just not use WebDriverWait.Until(), and use implicit waits on the main driver instead:
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
I give full credit to this answer on a different question for giving me the idea.
public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
{
try
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
return wait.Until(drv => drv.FindElement(by));
}
return driver.FindElement(by);
}
catch
{
throw;
}
}
or if you are having
NoSuchElementException
try this code
try
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds)).Until(ExpectedConditions.ElementIsVisible(by));
}
return driver.FindElement(by);
}
catch(Exception e)
{
throw;
}

Rerun CodedUI test in runtime

I have a CodedUI test. It sporadic fail by exception(can't focus element). Can I do something like this
[TestMethod]
public void MySporadicFailedTest()
{
try {
//Some Test action
}
catch((Exception ex)) {
if (ex is System.Exception.ElementNotFocused){
//retry test
}
}
}
This is something I deal with frequently when writing Coded UI tests. I almost always end up writing a simple extension method to handle retrying specific actions (not the entire test!). Sometimes, especially on pages with weird, non-standard markup or lots of AJAXy things happening, you'll just hit a situation where an action will fail one second because something isn't ready yet, then pass the next.
public static class TestRetryExtensions
{
public static void WithRetry<T>(this Action thingToTry, int timeout = 30) where T: Exception
{
var expiration = DateTime.Now.AddSeconds(timeout)
while (true)
{
try
{
thingToTry();
return;
}
catch (T)
{
if (DateTime.Now > expiration)
{
throw;
}
Thread.Sleep(1000);
}
}
}
}
Then, within my actual test:
uiMap.ClickSomeThing();
uiMap.EnterSomeText();
Action clickSomeOtherThingAction = () => uiMap.ClickSomeOtherThingThatFailsForNoReason();
clickSomeOtherThingAction.WithRetry<UITestControlHiddenException>(60);
It tries to perform the action. If it fails with an exception that you aren't aware of being an occasional "normal" thing, it throws the exception as normal. If it fails with an exception that you're telling it to retry on, it will keep trying that action (with a 1 second delay between retries) until the timeout is exceeded, at which point it just gives up and rethrows the exception.
As long as you can catch which ever exception is thrown, you can wrap your test code in a retry loop. Then it will try the test code a certain number of times before giving up:
for (var i = 0; i < TimesToRetry; i++)
{
try{
//perform test
//test ran correctly - break out loop to end test
break;
}
catch(Exception){
//might want to log exception
}
}
If the codedUI test continuously failing without proper reason you can added some code to enhance the test and make it fail safe. If test failing specifically when focusing to an element try to give focus to upper level element first and then try focusing child elements. This LINK may help you to write fail safe test cases.
we can include below line of code in test clean up method to re run the failed script
if (TestContext.CurrentTestOutCome==TestContext.unittestoutcome.failed)
{
var type=Type.GetType(TestContext.FullyQualifiedTestClassName);
if (type !=null)
{
var method=Type.GetMethod(TestContext.TestName);
var event=Activator.CreateInstance(type);
}
method.invoke(event);
}

Categories