Selenium – Extend Web Driver to Automate UI Testing

Selenium is a browser based testing automation framework. It is very simple to use and straight forward, all you need to do is download Selenium IDE for Firefox, and execute the test case and record the steps. Once recorded, it can be executed as may times as you want, simple!! You don’t need a tester after first execution 😉

However, Topic of discussion here is NOT Selenium Browser based automation. I am going to talk about using Selenium Web Drivers to extend NUnit testing framework to Automate execution of test cases in an integration environment, basically, execute UI test cases using web driver.

Getting Started

I’ll talk about creating an API that can be used with Web application and/or Windows application. To start with, you need to have a complete understanding of Selenium. Below are the components that we would write to complete this API.

  1. SeleniumCore – .NET C# Class Library to extend Selenium WebDriver.
  2. Services – Class library to interact with test-case repository.
  3. API – Windows Console Application.

How it Works

The selenium web driver is basically to execute NUnit test cases – or to execute unit tests, however, the aim here is to use it for executing integration test cases. Though it is not possible to completely automate SIT cases, we can automate re-occurring test cases. Basically all test cases that do not require data validation can be automated. I’d not rely on this to have complete SIT done, rather I’d use this to do a Smoke Test in SIT environment post major deployments. We would use the Web Drivers from Selenium to invoke browser and execute test cases. We will use Webdriver to execute test cases (NUnit) stored in database or we will get parameters from database to load web-pages and validate elements on page. We will also incorporate features like taking screenshot of valid test case execution.

Let’s Start

Let us write a custom Selenium engine to use Webdriver to execute test case. We will take the webdriver(IWebDriver) and create an instance of it. We will use Internet Explore to execute all our test cases as it is one of the most common browsers. To use IE, we need to download and copy the driver to application “bin” folder and ensure that it is available there. Download Selenium Internet Explorer driver from here.

Create an Instance of Internet Explorer Driver

Create a singleton instance of selenium internet explorer driver.

    public sealed class InternetExplorer
    {
        private static volatile IWebDriver instance;
        private static object syncRoot = new object();

        private InternetExplorer() { }

        public static IWebDriver Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new InternetExplorerDriver(new InternetExplorerOptions() { IntroduceInstabilityByIgnoringProtectedModeSettings = true });
                    }
                }
                return instance;
            }
        }
    }

Search Based on Link Text

Selenium allows you to search or execute test case using various elements on an html/aspx page. When I say elements on a page, it is, Link Text, Element Id, CssClass Name, attributes and so on.. Basically html tags/elements. Selenium web driver can look for a particular text n an element – this search is run on a response when a URL is streamed. If the Link Text/Search criteria fails, web driver throws an exception with specific text indicating that search failed/test case failed.

    public class LinkText
    {
        private List<Results> results { get; set; }

        public LinkText()
        {
            results = new List<Results>();
        }

        /// <summary>
        /// Search based on link text
        /// </summary>
        /// <param name="searchOptions"></param>
        /// <returns></returns>
        public List<Results> Search(Options searchOptions)
        {
            var dbTestCase = new SeleniumExtension.Services.MockSqlServices().GetSimpleDataObjects();
            foreach (var item in dbTestCase)
            {
                InternetExplorer.Instance.Navigate().GoToUrl(item.Url);
                foreach (var keyword in item.Keywords)
                {
                    try
                    {
                        IWebElement search = InternetExplorer.Instance.FindElement(By.LinkText(keyword));
                        results.Add(new Results()
                        {
                            Keyword = keyword,
                            Status = "Pass",
                            Url = item.Url
                        });
                    }
                    catch (Exception ex)
                    {
                        if (ex.Message.Contains(String.Format("Unable to find element with link text == {0}", keyword)))
                        {
                            results.Add(new Results()
                            {
                                Keyword = keyword,
                                Status = "Fail",
                                Url = item.Url
                            });
                        }
                    }

                    if (searchOptions.TakeScreenShot)
                    {
                        Features.TakeScreenshot.Snap(InternetExplorer.Instance, Utilities.Utilities.GetFileName(item.Url));
                    }
                }
            }
            return results;
        }
    }

Selenium features

Selenium offers various features, one of them is implemented here, to take screenshot. Here, I’ve extended the webdriver and made use of the selenium screen shot feature to take pages while executing the WebDriver.

    public class TakeScreenshot
    {
        public static void Snap(IWebDriver driver, string fileName)
        {
            ITakesScreenshot screenShotDriver = driver as ITakesScreenshot;
            Screenshot screenShot = screenShotDriver.GetScreenshot();
            var parentFolder = AppDomain.CurrentDomain.BaseDirectory;
            var folder = Path.Combine(parentFolder, DateTime.Now.ToString("dd-MM-yyyy"));
            if (!System.IO.Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }
            fileName = string.Format("{0}\\{1}", folder, fileName);
            screenShot.SaveAsFile(fileName, ImageFormat.Png);
        }
    }

How to Run Dynamic Test Cases

If you are familiar with Selenium, you should have already used Selenium IDE. If not, all you need to do is, download and install selenium IDE for FireFox. Once you the IDE installed, open the website you want to test and enable Selenium Web IDE and then start execution of UI test case. This will record the execution, once this is recorded. it can be exported as C# NUnit code using Selenium UI. This code is stored in database and executed dynamically later, n number of times as and when required. Thus automating Functional UI testing.

    public class DynamicCodeExecution
    {
        public static List<Results> AutoExecuteCode()
        {
            CSharpCodeProvider provider = new CSharpCodeProvider();
            ICodeCompiler compiler = provider.CreateCompiler();
            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            parameters.IncludeDebugInformation = false;
            parameters.TreatWarningsAsErrors = false;
            parameters.CompilerOptions = string.Format("/lib:{0}", "c:\\Selenium\bin");
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Core.dll");
            parameters.ReferencedAssemblies.Add("WebDriver.dll");
            parameters.ReferencedAssemblies.Add("SeleniumExtension.dll");
            string dynamicCode = new SeleniumExtension.Services.MockSqlServices().GetDynamicDataObjects().FirstOrDefault().DynamicCode; //call db and get the code
            parameters.GenerateInMemory = false;
            CompilerResults compiled = provider.CompileAssemblyFromSource(parameters, dynamicCode);
            if (compiled.Errors.HasErrors)
            {
                string errorMessage = "Has an Error : \n";

                for (int i = 0; i < compiled.Errors.Count; i++)
                {
                    errorMessage = errorMessage + "\r\nLine : " + compiled.Errors[i].Line.ToString() + " - " + compiled.Errors[i].ErrorText;
                }
                throw (new Exception(errorMessage));
            }

            Assembly assembly = compiled.CompiledAssembly;
            object instanceObject = assembly.CreateInstance("SeleniumExtension.Services.MockDynaObject");
            if (instanceObject == null)
            {
                throw (new Exception("Could not create an instance of dynamic object or the object was null"));
            }

            object[] codeParams = new object[0];

            try
            {
                object objResults = instanceObject.GetType().InvokeMember("Run", BindingFlags.InvokeMethod, null, assembly, codeParams);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            if (instanceObject != null)
                return (List<Results>)instanceObject;
            return null;
        }
    }

Source code for download

Download the source code selenium test case automation from here. The implementation require you to place Internet Explorer local host driver in the application execution path (bin) folder. Also make sure that you update the code to point to actual bin – this is required to execute the dynamic assembly.

Codeplex: https://seleniumautomation.codeplex.com/

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s