Code & QA

Interfaces

Before starting the development of the framework design I have composed the following principles which I suppose will make the framework well designed:

1. The application under test is a separate class. It consists of web pages which are declared inside the class as its properties. Usually it is sufficient to have only one instance of the application but since the class of the tested application will be designed as non-static, there still is the possibility to create a number of the application instances during tests run session, similar to real world when I open the same site in different browsers or in different browser tabs.

2. Every application page is a separate class as well. An individual class is created for every single page. So, there will be as many web page classes in the framework as there actually web pages are in the tested application. Though it seems that the number of page classes may be huge, in the real world even very big web applications hardly have more than one hundred pages. Most of them consist of about a couple of dozens of ones.

3. Every web page consists of web elements located on it. Every single class of a web page is unique and there may be only one instance of a page in the framework. I decided that declaring pages as static is a waste of memory and makes the design less managed. That’s why instances of web pages will be declared as properties of the application class. Following this way, I will be able to refer to only one instance of a page at a time in tests. This solution is very simple and pretty elegant. Surely, there still remains a possibility to create a number of page instances explicitly.

4. Every type of web element is a separate class. Examples of such types are: button, textbox, table, link, checkbox, tree-view, label, etc. There may be a lot of elements of the same type on a page.

5. Every type of web element has its own methods and properties unique for the type. For example, textbox has TypeText(string text) method which is not applicable to button element. Testing of the application is provided via the interaction with web elements through their methods and properties.

Scheme of classes:

clip_image002

In code it looks like:

[gist id=4ca0728dd74c0115965d54c8b92547d5]

In order to set up the structure of future classes I designed a set of interfaces which should be implemented by mentioned classes. The interfaces are located in the project Mapping in the Interfaces.cs file:

using Mapping.WebElements;

using OpenQA.Selenium;

using OpenQA.Selenium.Support.UI;

namespace Mapping

{

/// <summary>

/// Describes a web page

/// </summary>

public nterface IWebPage

{

string Name { get; set; } //name of a page as you call it

string Title { get; } //page title

string Url { get; } //page address

bool IsLoaded { get; } //indicates if a page is completely loaded

}

}

I also added a couple of auxiliary entities – enumerators and classes which are used with my interfaces.

/// <summary>

/// defines names of conditions which are used for click action result verification

/// </summary>

public enum ClickValidator

{

AlertDisplayed,

NumberOfWindowsChanged,

PageHashCodeChanged,

PageUrlChanged,

PageTitleChanged

}

/// <summary>

/// names of click actions used for interaction with web elements

/// </summary>

public enum ClickAction

{

Click, DoubleClick,

SendKeyEnter, SendKeyReturn,

SendKeySpacebar,

MouseLbClick,

MouseRbClick,

JsClick,

Hover

}

I added new folder WebElements to the Mapping project and put new file WebElement.cs to it. For now this class is only a mock and does nothing but allows designing IClickableElement interface without errors.

namespace Mapping.WebElements

{

public class WebElement

{

}

}

Ok, now I can add the next interface, IClickableElement, to Interfaces.cs file

/// <summary>

/// web element which may be clicked

/// </summary>

interface IClickableElement

{

void Click();

void DragNDrop(IWebElement target);

void DragNDrop(WebElement target);

void DragNDrop(int x, int y);

}

The following interfaces are prototypes of most used common web elements.

/// <summary>

/// web button

/// </summary>

interface IButton : IClickableElement

{

string Text { get; }

string Tooltip { get; }

}

/// <summary>

/// Link

/// </summary>

interface ILink : IButton

{

string Href { get; }

}

/// <summary>

/// checkbox

/// </summary>

interface ICheckbox

{

string Tooltip { get; }

bool IsSelected { get; }

void Select();

void Deselect();

}

/// <summary>

/// dropdown list

/// </summary>

interface IDropdownList : IClickableElement

{

SelectElement SelectElement { get; set; }

void SelectByText(string text);

void SelectByIndex(int index);

void SelectByValue(string value);

void SelectByTextPart(string text);

void SelectMultipleOptions(params string[] texts);

void SelectMultipleOptions(params int[] indexes);

}

/// <summary>

/// image (picture), imagebutton, imagelink

/// </summary>

interface IImage : IClickableElement

{

string Tooltip { get; }

string Src { get; }

}

/// <summary>

/// label, plain text

/// </summary>

interface ILabel

{

string Text { get; }

}

/// <summary>

/// textbox

/// </summary>

interface ITextbox

{

string Text { get; }

void Clear();

void AppendText(string text);

void TypeText(string text);

}

I believe anyone can understand what the interfaces define just by their names.

[row]
[column lg=”4″ md=”12″ sm=”12″ xs=”12″ ]
Running tests on Android [/column]
[column lg=”4″ md=”12″ sm=”12″ xs=”12″ ]
Table Of Content
[/column]
[column lg=”4″ md=”12″ sm=”12″ xs=”12″ ]
Extension methods
[/column]
[/row]

Leave a Reply