Showing posts with label Object Repository. Show all posts
Showing posts with label Object Repository. Show all posts

Thursday, 10 July 2014

Object Repository Framework in CodedUI for Windows applications

Hope everyone has gone through my Object Repository Framework in CodedUI for Web Applications
if not you can check those below

Object Repository Framework in CodedUI for Web Applications - Type1
Object Repository Framework in CodedUI for Web Applications - Type2

I was thinking it would even work for the Web Applications, however its not. So came up with the new similar framework.

Before stepping into the framework lets have a look how exactly the controls are defined.


Figure1

As we see in the Figure1, UICalculatorWindow is the main window for each control/button in the Calculator.
Surprisingly every control/button will be having a window upon it defined in the Windows applications.

so while coding it should be looking this way

class MainWindow
{
       property ChildWindow
}
class ChildWindow
{
       property Button
}

For each Childwindow and its own button, we see the FriendlyName as common.
so this FriendlyName should be the unique property which we are using as the search property.

This whole thing can be made a generic, so that it can be used for any control/button in the Calculator window


Step1:

As we did in the framework of Web applications, we are going to have two files added

Figure2

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



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 - done have spaces. those spaces after comma are just for better understanding)

ObjectName,         ObjectType,        Property,              Value
1,                           Button,                FriendlyName,       1
2,                           Button,                FriendlyName,       2
Add,                      Button,                FriendlyName,       Add 

ObjectName is the unique name given for the each object. 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());
            }
        }
        public void SetDataDic(string DicKey, string value1, string value2)
        {
            dataKey[DicKey].Add("Name", value1);
            dataKey[DicKey].Add("Value", value2);
        }
    }
}



Step4:

Now the below code is to be pasted in the UIMap.cs

public partial class UIMap
    {
// GenericParent is the Main Window with respect to Figure1
     public GenericParent GenericParent
        {
            get
            {
                if ((this.mGenericParent == null))
                {
                    this.mGenericParent = new GenericParent();
                }
                return this.mGenericParent;
            }
        }
        private GenericParent mGenericParent;
    }



public class GenericParent : WinWindow
    {
//Main Window i.e. GenericParent is defined directly without any OR
        public GenericParent()
        {
            this.SearchProperties[WinWindow.PropertyNames.Name] = "Caluclator";
            this.SearchProperties[WinWindow.PropertyNames.ClassName] = "CalcFrame";
            this.WindowTitles.Add("Calculator");
        }
       //Function used to return the ChildWindow with property from the ObjectRepository.csv
        public GenericWindow ReturnWinWindow(string Name)
        {
            cntrlName = Name;
            this.mGenericWindow = new GenericWindow(this,Name);
            return this.mGenericWindow;
        }
        #region Fields
        public GenericWindow mGenericWindow;
        public string cntrlName;
        #endregion

    }


public class GenericWindow : WinWindow
    {
        public GenericWindow(UITestControl searchLimitContainer, string controlName) :
            base(searchLimitContainer)
        {
            string[] oPropNames = DataDictionary.excelread.dataKey[controlName]["Name"].Split('|');
            string[] oPropTypes = DataDictionary.excelread.dataKey[controlName]["Value"].Split('|');
            Assert.AreEqual(oPropNames.Length, oPropTypes.Length);
            for (int i = 0; i < oPropNames.Length; i++)
            {
                this.SearchProperties[oPropNames[i]] = oPropTypes[i];
            }
            #region Search Criteria
            this.WindowTitles.Add("MRImport");
            #endregion
        }

        #region Properties
        public WinControl GenericControl
        {
            get
            {
                if ((mGenericControl == null))
                {
                    //if control is a combobox. this is irrespective of Calculator
                    if (this.ClassName.Contains("ComboBox"))
                    {
                        this.mGenericControl = new WinComboBox(this);
                    }
                    //if the control is a button Button
                    if (this.ClassName.Contains("Button"))
                    {
                        this.mGenericControl = new WinButton(this);
                    }
                }
                return mGenericControl;
            }
        }
        #endregion

        #region Fields
        private WinControl mGenericControl;
        #endregion
}


Step5:


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

[TestMethod]
// lets perform a simple Addition operation
public void CodedUITestMethod1()
{
 UIMap.ReadCSV();
               Mouse.Click(this.GenericParent.ReturnWinWindow("1").GenericControl);
           Mouse.Click(this.GenericParent.ReturnWinWindow("Add").GenericControl);
           Mouse.Click(this.GenericParent.ReturnWinWindow("2").GenericControl);
}

You are done :)

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


Thursday, 19 June 2014

Object Repository Framework in CodedUI for Web applications- Type 2

After working on the Object repository framework in Codedui, there are few more modifications done for the same, which would be bit more simple than earlier.

we follow the same steps till 3rd step as mentioned in the Object repository framework in Codedui, and the generic functions which are defined in the earlier one would vary.

Step 4:

Instead of going with different functions as mentioned in the before framework, we can go with a single function which can do every action we needed. However i thought of having 3functions which would be helpful

Functions in earlier framework


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

Updated Functions in this Framework

Object(string ObjectName) - this function returns the object by the properties mentioned in the CSV file

SetObject(string ObjectName, string value) - this function calls the Object function and for that particular object, depending upon the control type, the value is used.
  • if control is an edit, then it enters the value in editbox
  • if control is an Combobox, then it select the value item provided
  • if control is an checkbox, if value is true - it checks, if false - it unchecks
  • if control is an button, if value is true - it clicks the button
  • ........
GetObject(string ObjectName, string PropertyName) - this function returns the value of the property you provide in the PropertyName which can be used for any verifications/assertions

These functions are to be written in the UIMap file


 public static HtmlControl Object(string HtmlObjectName)

        {

            string objParentName = DataDictionary.excelread.dataKey[HtmlObjectName]["Parent"];

            HtmlControl objParentObj = GetParentOf(objParentName);

            HtmlControl obj;

            obj = new HtmlControl(objParentObj);

            string[] oPropNames = DataDictionary.excelread.dataKey[HtmlObjectName]["Name"].Split('|');

            string[] oPropTypes = DataDictionary.excelread.dataKey[HtmlObjectName]["Value"].Split('|');
            Assert.AreEqual(oPropNames.Length, oPropTypes.Length);
            for (int i = 0; i < oPropNames.Length; i++)
            {
                obj.SearchProperties[oPropNames[i]] = oPropTypes[i];
            }
            obj.FindMatchingControls();
            return obj;
        }



public static void SetObject(string HtmlObjName, string value)
        {
            UITestControlCollection collection;
            collection = Object(HtmlObjName);
            string cntrltype = collection[0].GetProperty("ControlType").ToString();
            switch (cntrltype)
            {
                case "Edit":
                    collection[0].SetProperty("Text", value);
                    //  myEdit.Text = value;
                    break;
                case "ComboBox":
                    collection[0].SetProperty("SelectedItem", value);
                    break;
                case "CheckBox":
                    bool value1 = bool.Parse(value);
                    collection[0].SetProperty("Checked", value1);
                    break;
                case "Button":
                    bool value2 = bool.Parse(value);
                    if (value2)
                        Mouse.Click(collection[0]);
                    break;
                default:
                    break;
            }
        }



public static string GetObject(string HtmlObjName, string PropertyName)
        {
            UITestControlCollection collection;
            collection = Object(HtmlObjName);
            return collection[0];
        }


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


Please let me know if any modifications or any changes which would help it more better.

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.