3

I have a number of tests which are run using Selenium and WinAppDriver. Sometimes the test gets passed, often Selenium doesn't find an element or click the wrong element even though it had passed the same test before.

I'm not sure why this happening. It could be selenium but it is more than likely my code.

Any suggestions on how I can make my tests tighter to prevent this in the future?

I have a BaseClass where I've SetUp() Method and The base class inherited in UnitTestClass.

In BaseClass, I check if I can click a "Maximize" element if it can't then I catch it and ignore it. Sometimes it works fine and sometimes it clicks on the top left of my screen

following is my code:

BaseClass

public class ExcelBaseClass
{
    private string excelId = OfficeVersion.Excel();
    private const string AppDriverUrl = "http://127.0.0.1:4723";
    public static WindowsDriver<WindowsElement> excelSession;
    public static WebDriverWait webDriverWait;
    public static DesiredCapabilities appCapabilities = new DesiredCapabilities();

    [TestInitialize]
    protected virtual void SetUp()
    {
        try
        {


            appCapabilities.SetCapability("app", excelId);
            var initialSession = new WindowsDriver<WindowsElement>(new Uri(AppDriverUrl), appCapabilities);
            var capabilities = new DesiredCapabilities();
            capabilities.SetCapability("app", "Root");
            excelSession = new WindowsDriver<WindowsElement>(new Uri(AppDriverUrl), capabilities);
            CommonMethods.keyCheck(excelSession);
            webDriverWait = new WebDriverWait(excelSession, TimeSpan.FromSeconds(60));
            CommonMethods.IsElementDisplayed(excelSession, new StackTrace(true).GetFrame(0).GetFileLineNumber(), new StackTrace(true).GetFrame(0).GetMethod(), "CreateErrorIcon", "Create error when launching Excel");
            try
            {                   
               webDriverWait.Until(ExpectedConditions.ElementTo‌BeClickable(excelSession.FindElementByName("Maximize"))).Click();
            }
            catch (Exception)
            {
                //ignore
            }
        }
        catch (Exception)
        {

            CommonMethods.ExceptionHandler("WinApp Driver failed to load Excel", new StackTrace(true).GetFrame(0).GetFileLineNumber(), new StackTrace(true).GetFrame(0).GetMethod(), excelSession);
        }

    }
}

UnitTestClass

[TestMethod]
public void newExcelWorkbook()
{
    try
    {
        base.SetUp();
        webDriverWait.Until(ExpectedConditions.ElementTo‌BeClickable(excelSession.FindElementByName("Blank workbook"))).Click();
        webDriverWait.Until(ExpectedConditions.ElementTo‌BeClickable(excelSession.FindElementByName("Create"))).Click();
        webDriverWait.Until(ExpectedConditions.ElementTo‌BeClickable(excelSession.FindElementByName("New"))).Click();
        webDriverWait.Until(ExpectedConditions.ElementTo‌BeClickable(excelSession.FindElementByName("E  Sample Data"))).Click();
        CommonMethods.IsElementDisplayed(excelSession, new StackTrace(true).GetFrame(0).GetFileLineNumber(), new StackTrace(true).GetFrame(0).GetMethod(), "CreateErrorIcon", "Error appeard while selecting the E Sample Data button");
    }
    catch (Exception)
    {
        CommonMethods.ExceptionHandler("Couldn't find element", new StackTrace(true).GetFrame(0).GetFileLineNumber(), new StackTrace(true).GetFrame(0).GetMethod(), excelSession);
    }

    TearDown();

}
  • I think you need to wait for the element to exist first using an ExpectedConditions.ElementExists(By selector) before you wait for it to be clickable. You should be more specific about the Exceptions you're catching so you don't eat everything. My guess in this case you're getting a NoSuchElementException because ElementToBeClickable expects the element to already be there. So you have to check for that first. I hope that made sense, give it a try and reply how it goes. – mrfreester Aug 3 '17 at 18:19
  • Just to be a little more clear on what I think you need to do for the not able to find the element part of your question... By maximizeBy = By.Name("Maximize"); webDriverWait.Until(ExpectedConditions.ElementExists(maximizeBy)); webDriverWait.Until(ExpectedConditions.ElementToBeClickable(excelSession.FindElement(maximizeBy)).Click(); The documentation makes it sound like you might be able to pass the By to ElementToBeClickable to avoid the exception also – mrfreester Aug 3 '17 at 18:33
  • @mrfreester thanks for your comment. Surely by waiting for an element to be clickable the element should exist so is that not overkill? Also will this slow the tests down considerably if I follow this practice throughout all my tests? – Craig Gallagher Aug 4 '17 at 9:01
  • 1
    The overhead for adding an explicit wait would be almost negligible as they return as soon as the condition is met, time wouldn't be your biggest concern here, but keeping your code DRY could become an issue. I'll post an answer with some more detail. – mrfreester Aug 7 '17 at 14:32
1

This sounds like two different issues. 1. Sometimes you get a NoSuchElementException. 2. Sometimes selenium clicks the wrong element.

I'll focus on the 1st issue as the 2nd issue would probably need more debugging information.

You have a problem with this line:

webDriverWait.Until(ExpectedConditions.ElementTo‌BeClickable(excelSession.FindElementByName("Maximize"))).Click();

First, excelSession.FindElementByName(...) will be called, the result of that will be passed to the ElementToBeClickable method, and that result is passed to Until which will run that action until it returns true. This is a problem because excelSession.FindElementByName throws an exception if the element doesn't exist, so the result can't ever be passed to ElementToBeClickable.

The easiest solution is to pass a By to this method, as that version of ElementToBeClickable will wait until the By successfully finds the element. Or to be more accurate, it will return false if the element doesn't exist.

By maximizeBy = By.Name("Maximize"); 
webDriverWait.Until(
    ExpectedConditions.ElementToBeClickable(‌​excelSession.FindEle‌​ment(maximizeBy)).Cl‌​ick();

That should take care of your issue with it sometimes not clicking the maximize button due to a NoSuchElementException.

Another thing that is likely causing you a lot of grief, is you're eating way too many Exceptions, and then hiding the real exception by trying to guess why an exception was being thrown, and logging that. Generally speaking, try to avoid using Exceptions as logical paths. If an exception gets thrown, feel free to catch a specific Exception (something like NoSuchElementException, not Exception), do some logging or any cleanup that needs to happen, but still throw or attach the original exception message to your exception. Otherwise your going to run into confusing debugging problems.

Best of luck!

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.