Tuesday, October 6, 2015

Thoughts on C# and reimplementing the Abstract PageObject Pattern with C#

Quick Thoughts on C#

I've started a new job in a C#.Net shop after working in Python for 1 1/2 years.  One of the things I'm dealing with now is re-writing some of the framework stuff I've written over the years in C#.  There are some things I like and don't like about C# vs Python.

Likes

  • I like strongly typed languages in that tools for linting, syntax checking, and re factoring tends to be much better.


Don't likes

  • Closures are a bit tricky to deal with.  In python it was very easy to go crazy with lambda statements, which I did very liberally especially with wait and exception handling wrappers.
  • Decorators didn't seem as straight forward.
  • REPL - scripting languages you can evaluate nearly anything in the REPL.  C# however, you can do somethings, but say importing new classes gets tricky.




Re-implementing Abstract PageObject pattern in C#

Thought I share this, since I've reimpelmented it in C#.  The orginal implementation I've done in Java you can find here, http://engineeringquality.blogspot.com/2012/06/creating-generic-advanced-page-factory.html.

For C#, most of it follows very similar to Java.

using System;
using System.Linq;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
 
namespace web
{
    internal class AbstractPageFactory
    {
        /// <summary>
        /// An advanced version of Selenium's PageFactor.InitElements that uses reflection to infer subtypes.
        /// </summary>
        /// <typeparam name="T">PageObject or Interface</typeparam>        
        /// <param name="searchContext">Selenium webdriver or webelement</param>
        /// <returns></returns>
        public static T InitElements<T>(ISearchContext searchContext)
        {
            var type = typeof (T);
            var subtypes = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(s => s.GetTypes())
                .Where(type.IsAssignableFrom);
 
            Exception lastException = null;
            foreach (var subtype in subtypes.Where(subtype => subtype.IsClass).Where(subtype => !subtype.IsAbstract))
            {
                try
                {
                    var pageObj = Activator.CreateInstance(subtype, searchContext);
                    PageFactory.InitElements(searchContext, pageObj);
 
                    return (T) pageObj;
                }
                catch (Exception e)
                {
                    lastException = e;
                }
            }
 
            if (lastException != null)
                throw new NoSuchWindowException("Could not find a matching PageObject. Last exception:" + lastException);
 
            throw new NoSuchWindowException("No matching PageObjects found.");
        }
    }
}

No comments: