0

I have a lot of Page classes to work with, for my test automation. Each of them has three following essential elements:

  1. WebDriver
  2. Uri
  3. Essential element of that page.

I decided to make a base class for all the page class as follows:

internal class Page
{
    protected IWebDriver _webDriver;
    protected string _uri;
    protected By _essentialElementCriteria;

    internal Page(IWebDriver driver, WebDriverPageType pageType, string uri, By criteria)
    {
        try
        {
            PageLoader.LoadPage(driver, _uri, new SearchAndWaitCriteria(_essentialElementCriteria));
            this._webDriver = driver;
        }
        catch (Exception exc) { throw new PageLoadFailedException(pageType, exc); }
    }
}

A derived class would look like this:

internal class LoginPage : Page
{
    internal LoginPage(IWebDriver driver)
       : base (driver, WebDriverPageType.LoginPage, "loginpage_url", By.Id("xyz")) { }        

    // Other LoginPage specific methods like Login().
}

The PageLoader class is as follows:

internal class PageLoader
{
    internal static void LoadPage(IWebDriver driver, string uri, SearchAndWaitCriteria criteria)
    {
         if (driver == null) throw new ArgumentNullException("WebDriver is null.");

         driver.Navigate().GoToUrl(uri);
         var waitElement = driver.WaitForElement(criteria.SearchCriteria, criteria.MaximumWaitSeconds, criteria.SleepMilliSecondsBetweenTwoSearches);
         if (waitElement == null) throw new NotFoundException(String.Format("Failed to find the waitElement. Element details: {0}", criteria.SearchCriteria.ToString()));
    }

    internal static bool IsPageLoaded(IWebDriver driver, SearchAndWaitCriteria criteria)
    {
         IWebElement essentialElement = driver.GetElement(criteria.SearchCriteria);
         return essentialElement != null;
    }
}

My basic idea was to eliminate writing the same code of constructing pages, as I am going to create a lot of page classes. Hence, I "commoned out" that code to the base class, along with the help of the PageLoader class. I still think something is not quite right. I have given the responsiblity of throwing exception to the base class, which is fine. But, I need to give the derived class's PageType as an argument to the base class just to do that, which doesn't seem good to me.

What improvements could you suggest in this design? Should I eliminate a base class, and use composition instead? I think I may be able to merge PageLoader and Page class to achieve that. Not sure on that idea, just a thought.

Ray Hayes
  • 14,896
  • 8
  • 53
  • 78
bhootjb
  • 1,501
  • 1
  • 21
  • 33
  • 1
    Why don't you use the `Type` of the `Page` itself? You can do `throw new PageLoadFailedException(this.GetType())`. – Steven Jul 05 '12 at 11:11
  • @Steven Ok. My bad. That will save me a parameter. Other than that, does my design seem good enough. – bhootjb Jul 05 '12 at 11:17
  • 1
    ["Should I eliminate a base class, and use composition instead?"](http://en.wikipedia.org/wiki/Composition_over_inheritance) – Steven Jul 05 '12 at 11:19

0 Answers0