Writing a UI automation framework with C#, part one

I spent some time earlier this year digging into UI automation, specifically an implementation a peer had started using C#, Selenium WebDriver and NUnit. At the time there was an ask for us to implement a sanity-level test of our team’s product and it seemed like the right time to become more familiar with the concepts around working with WebDriver.

What I found in the existing framework was an abstraction layer for WebDriver, and other objects to provide functionality for making testing more presentable to testers that had some familiarity with object-oriented concepts. There was also logic in the test fixture setup and teardown (a concept introduced from the NUnit test framework) to handle loading language-specific variables. These were all good features making a tool we could use in a variety of ways, and they aligned with what I was reading online, and we’re still using them today to develop our tests.

When I started focusing more on the UI automation we were doing, I started writing my own UI automation framework. My approach was to make something comparable based on what I was learning about C# and WebDriver, without using any reference material. Within a couple days I had something running, and in another day I had something that ran on Windows and Linux.

This is evidently a long preamble so that when I start explaining my design I don’t sound self-aggrandizing. There is also nothing particularly special in this article that can’t be found online and written by people that are much more into this than I am.

Introduction

The UI automation framework I wrote contains a WebDriver abstraction, an element locator, explicit wait conditions and objects to support the page object design pattern.

WebDriver Abstraction

In order to provide more friendly methods to some of the obscured WebDriver functions I wanted access to, I created an abstraction object that translates something I want to do into the appropriate WebDriver call. For example:

public void SetImplicitWait(int seconds)
{
webdriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(seconds));
}

Aside from presenting a subset of more direct and specific user interactions with the WebDriver, this object also represents actions the user wants to do. So there are methods for clicking an element or entering text into an element on the page. (It’s worth mentioning that the elements are actually located in the DOM, but that the end result is a page being rendered in a browser, so I use page because it’s more evident.)

The WebDriver interfaces are still accessible through this object as well, so it’s possible to make calls directly if it doesn’t make sense to work through this abstraction layer. One example of this from my experiences so far, are for selecting a group of elements instead of one specific element using a FindElements method call.

Element Locator

Specifying elements on the page is a common action when working with UI automation using the WebDriver. So that a single object with readable methods would provide a way of returning a By object (used for working with other WebDriver methods, like the very important FindElement) I created a static object that did this. Here is an example of a call:

public static By ElementByValue(string value)
{
return By.XPath(String.Format("//*[text()='{0}']", value));
}

Others are more direct, taking a name of an element and doing a more direct lookup, for example.

Explicit Waits

WebDriver has the concept of implicit and explicit waits. In C#, it has a specific way of providing a wait condition through a lambda statement. I’ve found there are some common situations where you want to be able to wait, and that some of these are when you’re interacting with the WebDriver, but that this is also relevant when working with pages or tests. I made this functionality visible to any object wanting access to it.

An example of providing a wait for an element to become visible looks like:

public static void UntilElementIsVisible(Driver driver, By locator, int timeout)
{
WebDriverWait wait = new WebDriverWait(driver.webdriver, TimeSpan.FromSeconds(timeout));
wait.Until((d) => { return d.FindElement(locator).Displayed; });
}

Page Object Pattern Objects

From the different patterns I’ve seen, and from the different ways I’ve written Selenium scripts, for comprehensive functional automated UI testing, I like the page object pattern. Although I’m not as strict about how it’s generated or used, I found it useful to provide a base object with a few methods for what I would expect someone writing a test to want from a page they were specifying. These methods are for determining if an element is visible to a user or if an element has a specific value. An example of this would be:

public bool ElementHasValue(By locator, string value)
{
IWebElement element = driver.webdriver.FindElement(locator);
return (element.Text == value);
}

This also highlights another point in my overall design, to leave user actions to the Driver object and page validation actions to the base Page object.

In Closing

In writing this I hope it helps others who were at the spot I was at earlier this year, putting together the pieces of UI automation, in getting started on their journey.

For those interested, I’ve made this framework available on GitHub. I called it Kitsune, because right now it works with Firefox and I’m a fan of Japanese folklore and games which promote that rich cultural tradition. It has no relation to the Mozilla Foundation’s Kitsune project and they do two very different things.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

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

%d bloggers like this: