0
votes

We have an existing UI automation framework in C# and based on knowledge at the time we used PageFactory to initialize the elements within the page files. Recently I've read more on the subject and there appears to be no real benefit to using PageFactory in C# so I'm attempting to re-write the pages using fields instead. One thing I'm having an issue with now those is getting my extended methods to work.

For example: In the current implementation I have an element identified like this: [FindsBy(How = How.LinkText, Using = "Authenticate")] private IWebElement BstHomePageHeader;

    public IWebElement getBstHomePageHeader()
    {
        return BstHomePageHeader;
    }

There is a helper method which checks if the element exists in certain cases and it's called like this from within a test:

home.getBstHomePageHeader().DoesElementExist().Should().BeTrue("User was not taken to the home page.");

The code within the "DoesElementExist" method has a 5 second wait applied, continually validating the element.Displayed check and it's ignoring the NoSuchElementException, ElementNotVisibleExpection and WebDriverTimeoutException. If the element is not returned within 5 seconds a false is returned to the main call and the fluent assertion message is thrown.

When I remove PageFactory the element is now created like below (in the same page file): public IWebElement getBstHomePageHeader => driver.FindElement(By.LinkText("Authenticate"));

If I try to apply the same helper method to it like below the DoesElementExist part of the line of code no longer applies. The NoSuchElementException is thrown directly in my page file and therefore the fluent assertion message isn't returned. home.getBstHomePageHeader.DoesElementExist().Should().BeTrue("User was not taken to the home page.");

Is it possible in a non-PageFactory design to not have the page class throw the NoSuchElementException so the test can handle the failure?

2

2 Answers

1
votes

Well, for what it's worth I've come up with a different solution. I'm not sure it's the best one but I believe it will work. In my page file I'm looking the elements up with this: public IWebElement getBstHomePageHeader => LookUpElement(By.LinkText("Authenticate")); I created a base class which is hosting the LookUpElement method and that looks like protected IWebElement LookUpElement(By locator) { try { return wait.Until(driver => driver.FindElement(locator)); } catch (NoSuchElementException) { } catch (ElementNotVisibleException) { } catch (WebDriverTimeoutException) { } return null; }

The wait logic is the same as before. The only other change is I've changed how I was asking the question within the test. It now looks like this if (home.getBstHomePageHeader == null) false.Should().BeTrue("User was not taken to the home page."); test.Log(Status.Pass, "User is on the home page.");

So, I guess I didn't really answer my own original question but this workaround appears to work. We'll just have some re-writing to do in how we ask the questions.

0
votes

In java you would throw the exception up to the caller. Can you do that at all in C#?

This looks like it might help: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/creating-and-throwing-exceptions

Side note: We removed page factory containers from our code base too and it is so much cleaner. Each page class contains its own required elements and selectors at the top of the class. We also noticed stale element exceptions with the containers, even when it was setup properly.