Tuesday, 17 June 2014

Object Repository Framework in CodedUI for Web applications- Type 1


Earlier when i used to work with QTP tool, the objects are well organised in the object repository and it was very easy for the maintenance or to update any properties of objects.

Where as in CUIT we face an issue with maintaining an object repository. Once we record any test case and check for UIMap.Designer.cs file we see all the controls added and its a mess to understand what exactly is happening.

After a little RnD, i have come with a object repository kind of framework for my project which i am working on. Thought of sharing so it would be helping even other.

Figure1
As seen in the Figure1, there are two additional files which have been added i.e. DataDic.cs and ObjectRepository.csv.

Below are the steps to start with building a framework.
Step1:
Adding the Parent Controls to UIMap.

Figure2
As per the Figure2, UIGoogleDocument will be the parent map. Accordingly add all the parent controls in all the pages of you application. How to add a control without recording an action can be done as per the below link Adding-ui-control-to-uimap-without recording

Step2:

Add an .csv file to the solution, i.e. ObjectRepository.csv file as showing in the Figure1.

Let the data be added in the csv file as shown below.(Note - don't have spaces. those spaces after comma are just for better understanding)

ObjectName,         ObjectType,        ParentObject,   Property,        Value
UserName,            HtmlEdit,             LoginDoc,        Name,             tbUserID
Password,              HtmlEdit,             LoginDoc,        Name,            tbPassword
ForgotPassword,    HtmlHyperLink,   LoginDoc,       Name|Id,        cbURL|cbURL
Login,                     HtmlInputButton, LoginDoc,       Name|Type,    LoginButton|submit


ObjectName is the unique name given for the each object. Parent Object is under which parent the object come. Property is what properties to be defined and value is the corresponding value for name provided

Step3:

Add an DataDic.cs file, in which we define the DataDictionary and add the values in the DataDictionary by reading the values from excel sheet.

using Microsoft.VisualStudio.TestTools.UITesting;
using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;
using System.Data;
using System.IO;

namespace DataDictionary
{
    public class excelread
    {
        public static Dictionary<string, Dictionary<string, string>> dataKey = new Dictionary<string, Dictionary<string, string>>();
        public void Readcsv()
        {
            dataKey.Clear();
            string fullPathToExcel = @"C:\Users\Administrator\Documents\Visual Studio 2012\Projects\CodedUITestProject1\CodedUITestProject1\ObjectRepository.csv";
            StreamReader reader = new StreamReader(File.OpenRead(fullPathToExcel));
            while (!reader.EndOfStream)
            {
                string line = reader.ReadLine().ToString();
                string[] values = line.Split(',');
                string key = values[0].ToString();
                Dictionary<string, string> datavalues = new Dictionary<string, string>();
                dataKey.Add(key, datavalues);
                SetDataDic(key,values[2].ToString(),values[3].ToString(),values[4].ToString());
            }
        }
        public void SetDataDic(string DicKey, string value1, string value2, string value3)
        {
            dataKey[DicKey].Add("Parent",value1);
            dataKey[DicKey].Add("Name", value2);
            dataKey[DicKey].Add("Value", value3);
        }
    }
}


Step4:

For my project what i have done is defined the functions which are used commonly. for example

SetText(string ObjectName,string Value) - this function gets the object by the properites mentioned in csv file with the unique objectname and assignes the value in the TextBox

SelectListItem(string objectName,string value) - this function gets the object by the properties mentioned in csv file and slects the value in listbox

ClickButton(string ObjectName) -  this function gets the object with objectname from csv file and clicks it

Note - All these functions are defined in the UIMap.cs file


public static void SetText(string HtmlEditObjectName, string TextToEnter)
        {
            string objParentName = DataDictionary.excelread.dataKey[HtmlEditObjectName]["Parent"];
            HtmlControl objParentObj = GetParentOf(objParentName);
            HtmlEdit obj;
            obj = new HtmlEdit(objParentObj);
            string[] oPropNames = DataDictionary.excelread.dataKey[HtmlEditObjectName]["Name"].Split('|');
            string[] oPropTypes = DataDictionary.excelread.dataKey[HtmlEditObjectName]["Value"].Split('|');
            for (int i = 0; i < oPropNames.Length; i++)
            {
                obj.SearchProperties[oPropNames[i]] = oPropTypes[i];
            }
            obj.FindMatchingControls();
            obj.Text = TextToEnter;
        }
        
        public static void SelectListItem(string HtmlComboBoxName, string ListvalueToSelect)
        {
            string objParentName = DataDictionary.excelread.dataKey[HtmlComboBoxName]["Parent"];
            HtmlControl objParentObj = GetParentOf(objParentName);
            HtmlComboBox obj;
            obj = new HtmlComboBox(objParentObj);
            string[] oPropNames = DataDictionary.excelread.dataKey[HtmlComboBoxName]["Name"].Split('|');
            string[] oPropTypes = DataDictionary.excelread.dataKey[HtmlComboBoxName]["Value"].Split('|');
            for (int i = 0; i < oPropNames.Length; i++)
            {
                obj.SearchProperties[oPropNames[i]] = oPropTypes[i];
            }
            obj.FindMatchingControls();
            obj.SelectedItem = ListvalueToSelect;
        }

         public static void ClickButton(string HtmlInputButtonName)
        {
            string objParentName = DataDictionary.excelread.dataKey[HtmlInputButtonName]["Parent"];
            HtmlControl objParentObj = GetParentOf(objParentName);
            HtmlInputButton obj;
            obj = new HtmlInputButton(objParentObj);
            string[] oPropNames = DataDictionary.excelread.dataKey[HtmlInputButtonName]["Name"].Split('|');
            string[] oPropTypes = DataDictionary.excelread.dataKey[HtmlInputButtonName]["Value"].Split('|');
            for (int i = 0; i < oPropNames.Length; i++)
            {
                obj.SearchProperties[oPropNames[i]] = oPropTypes[i];
            }
            obj.SearchProperties[HtmlInputButton.PropertyNames.Id] = null;
            obj.SearchProperties[HtmlInputButton.PropertyNames.Type] = "submit";
            obj.FindMatchingControls();
            Mouse.Click(obj);
        }

// parent added according to Figure2
        public static HtmlControl GetParentOf(string name)
        {
            switch (name)
            {
                case "LoginDoc":
                    CodedUITestProject1.UIGoogleWindowInternetWindow tmp = new UIGoogleWindowInternetWindow ();
                    return tmp.UIGoogleDocument;
                default:
                    return null;
            }
        }


Step 5:

In the CodedUItest1.cs call these functions accordingly to the test scenario as below

[TestMethod]

        public void CodedUITestMethod1()
        {
            UIMap.login();
            UIMap.ReadCSV();
            UIMap.SetText("UserName", "test");
            UIMap.SetText("Password", "password");
            UIMap.ClickButton("Login");
       }

You are done :)

You can even look at my other framework
object-repository-framework-in-codedui - Type 2


Please feel free if you got any better ideas or else if you feel any modifications could help in making this better.