Building Automation That Lasts
posted by Bryan on
Automated tests have an important role in the longevity of your product. There are pros and cons to having an automation suite, but I think the pros fully out weigh the cons. That being the case, how do you build an automation framework that will outlast the tools that are being used?
I have heard the same question recently probably about 2 dozen times. "How do I migrate my Selenium 1 tests to Selenium 2?" We have thousands and thousands of tests across several products, so I couldn't imagine rewriting all those tests every "x" number of years to be up to speed with the latest tools.
There are 3 parts to a stable automation framework that you should consider.
Layer 1: The actual framework (WatiN, Selenium, WebDriver, WatiR, etc)
You can pick whichever platform you want to write your tests on. This is sometimes decided by management based on experience of those on the team, tool set, skill set, etc. However, I recommend not building your own automation framework at this level. There are many out there and they all do different things. Find the tool you should use and go with it.
Layer 2: The framework you build
This framework should be the interceptor between both layers. It should be easily configured, allow for object oriented design and most of all - stable.
You need to create a way for Layer 1 to talk with Layer 3. Ultimately, the idea is to make it such that if a new automation framework comes out, you can plug it in at this layer without affecting your tests.
Example, the framework I used was built on WatiN. The primary browser of support was IE so it was a good fit. Since then, support has grown to include Firefox and Chrome. I didn't have to rewrite all my tests. All I did was wire up WebDriver into this layer and built a way to toggle which framework I want to use. Now I can run any of my tests on WatiN or WebDriver with their respective supported browsers.
Let's look at an easy way to implement this. Create a class such as "MappedElement".
public class MappedElement { public MappedElement(string elementType, string attribute, string value) { ElementType = elementType; Attribute = attribute; Value = value; } public string ElementType { get; private set; } public string Attribute { get; private set; } public string Value { get; private set; } }
Now, every time you want to interact with an element at Layer 3, you create an instance of a MappedElement with the pieces that fit. I know it's a textbox with an ID attribute of "j_username". Then, Layer 2 knows how to find only MappedElement objects. Which might look like one of the following:
//In tests (layer 3) MappedElement usernameField = new MappedElement("textbox", "id", "j_username"); mappedElement.Type(usernameField, "myusername"); //In Layer 2 public static void Type(MappedElement element, string text) { //add logic here to find by correct attributes, etc. //Also, add logic to identify which framework you are using, if multiple TextField textfield = browser.TextField(Find.ById(element.Value)); textfield.TypeText(text); //OR WebElement textfield = driver.FindElement(By.Id(element.Value)); element.SendKeys(text); }
Layer 3: Your automated tests
The automated tests live in this layer. They leverage the Layer 1 framework in every way possible but only done so through Layer 2. Meaning, your tests are written in such a way that you might not be able to tell what automation framework is actually being used. This is good. Now, there will be times where it doesn't make sense to add a certain bit of functionality into Layer 2 because it might be specific to one certain project. At that point, you can still access Layer 1's direct functionality but that is usually been low compared to all the tests overall.
Example:
if (framework.IsWebDriver()) { //do it this way } else if (framework.IsWatiN()) //do it another way }