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.