Encapsulating Your UI Test Automation

The Telerik Testing Framework and Selenium are two choices for test automation of web apps. If you’re wondering which one is right for you check out my article on the subject.

Once you pick a framework you’ll figure out how to get elements and click them, set their text content etc. That’s the easy part. For long term success you need test automation code written in a scalable manner.

For instance maybe there’s a button in a web page and you want to press it. So you write something like this (pseudo-code):

	Element submit = Browser.GetElement('myButtonId');
	submit.Click();

Easy enough. Now let’s say this is an entire form and you have two inputs fields followed by the same submit button. The form is contained within a div element. Our code gets expanded to automate the entire thing like so:

	Element firstName = Browser.GetElement('id=divContainerId > id=firstNameInputId');
	Element lastName = Browser.GetElement('id=divContainerId > id=lastNameInputId');
 
	firstName.set('John');
	lastName.set('Smith');
 
	Element submit = Browser.GetElement('id=divContainerId > id=myButtonId');
	submit.Click();

Easy still. Next let’s say that was Test 1 and we want to write Test 2. Test 2 will automate a different page in our application. That page reuses the same form we’ve already automated in Test 1. How do we proceed to automate the form in the new page? The obvious thing is to copy/paste our code from Test 1 into Test 2.

This is a bad approach because:

A) Maintenance suffers:

You have two instances of the same logic that need to be maintained separately. If for example your devs changes the ID of the firstName input field you have to manually update the code in two places.

B) Usability suffers:

It’s hard to look at the above code chunk and immediately know what it does. If someone other that the person who wrote it is contributing code they will have a hard time reusing that block.

Using encapsulation will solve these issues. Wikipedia’s definition of encapsulation is “A construct that facilitates the bundling of data with the methods (or other functions) operating on that data“.
The data in our case is the selectors we use to find the Form elements. The functions operating on the data are the actions of setting the text of the elements, clicking on the submit button etc. Let’s bundle these together by writing a Form class:

class Form {
    private string selector;
    private string firstNameSelector = "id=firstNameInputId";
    private string lastNameSelector = "id=lastNameInputId";
    private string submitButtonSelector = "id=myButtonId";
 
    //Constructor
    public Form(string formSelector){
            selector = formSelector;
    }
 
	public SetFirstName(string name) {
	Element firstName = Browser.GetElement(selector + ">" + firstNameSelector);
	firstName.set(name);
	Assert(firstName.text == name);
	}
 
	public SetLastName(string name) {
	Element lastName = Browser.GetElement(selector + ">" + lastNameSelector);
	lastName.set(name);
	Assert(lastName.text == name);
	}
 
	public SubmitForm() {
	Element submit = Browser.GetElement('id=divContainerId > id=myButtonId');
	submit.Click();
	//Do stuff to verify form is submitted
	}
}

A few things about this class:

  • The selector variables are initialized at the top by convention. They will need periodical maintenance so we need to find them easily.
  • The selector for the whole form is passed in the constructor. Assuming that there can be multiple instance of this form in one page that means we need a way of specifying the one- we want.
  • Each function verifies its expected result.

Ok, Writing that class was a bit of work but now you can fill out your form in Test 1 and Test 2 like this:

Form myForm = new Form("id=currentFormId");
form.SetFirstName("John");
form.SetLastName("Smith");
form.SubmitForm();

You can reuse this for all instance of the form in your application. It’s easy to use and easy to read. You need to become comfortable with this approach. All reusable widgets (DatePicker, Grid etc) in your application need to be encapsulated. If you’ve had to write the same piece of code twice in separately then you’re probably doing it wrong.

This outlines the most basic idea of encapsulation in a test automation context. If you don’t know how to work with classes and objects you should spend some time educing yourself on that stuff. You don’t need to be a senior programmer but you should definitely grasp the basics. I can recommend this course just because that’s what I first used to teach myself OOP.

Need help with your test automation? Let’s work together!

Leave a Reply

Your email address will not be published. Required fields are marked *