Tuesday 22 July 2014

Mapping a network drive in C#

         

            string path = @"\\IPADDRESS /user:DOMAIN\USERNAME PASSWORD";
            // Z is the name given to the mapped network drive
            string strMapDrive = "/C net use Z: " + path;
            string strUnMapDrive = "/C net use Z: /delete";
            if (Directory.Exists("Z:\\"))
            {
                System.Diagnostics.Process process = new System.Diagnostics.Process();
                System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                startInfo.FileName = "cmd.exe";
                startInfo.Arguments = strUnMapDrive;
                process.StartInfo = startInfo;
                process.Start();
                startInfo.Arguments = strMapDrive;
                process.StartInfo = startInfo;
                process.Start();
            }

Monday 14 July 2014

Easy way to provide the Search and Filter properties

If suppose there is a link and the following are the search and filter properties


SearchProperties[HtmlEdit.PropertyNames.Id] = "value"; 
SearchProperties[HtmlEdit.PropertyNames.Name] = "value"; 
FilterProperties[HtmlEdit.PropertyNames.LabeledBy] = null; 
FilterProperties[HtmlEdit.PropertyNames.Type] = "SINGLELINE/null"; 
FilterProperties[HtmlEdit.PropertyNames.Title] = null/value; 
FilterProperties[HtmlEdit.PropertyNames.Class] = "values/null"; 
FilterProperties[HtmlEdit.PropertyNames.ControlDefinition] = "values"; 
FilterProperties[HtmlEdit.PropertyNames.TagInstance] = "33"; 



Instead you can give those properties in one line as below

parentUIControl.SearchFor<HtmlEdit>( 
new { Id = "s", Name = "s" } , new { LabeledBy = null, Type = "SINGLELINE/null", Title = null / value, Class = "values/null", ControlDefinition = "values", TagInstance = "33"}    ); 

Sunday 13 July 2014

Creating Ordered tests in CUIT

Executing the automated test scripts in Batch. In CodedUI  we can create and execute the batch of Unit tests using Ordered test.

To create ordered test please follow the below steps:

1. Open CodedUI TestProject.
2. Click on Test tab >> New test.



3. Select Ordered Test 


-- We can give name to ordered test in Test name text box and click on OK button.

4.Then we need to select the unit test from list of available tests in the project.



5. In the Left side pane we can see the available tests.Either by double click on individual test or by selecting test and then click on ">" button will add the test to the ordered test list.To remove the test from "selected tests"- select the test from "selected tests"  list click on "<".



6.Now the very important point is to check the "continue after failure"checkbox.This ensures that if any test get failed during the ordered test execution, then the next test will be executed from the selected list.e.g In given example if "checkAddition.." test fails then the "CheckMultiplication.." will be executed. 



7. Now click on Save icon to Save the ordered test.


8. Now click on Run test and then results will be generated.
To Execute ordered test click on Test >>Windows>>Test List Editor



9. select the ordered test from the list and click on Run ordered test icon. OR by right click on the selected ordered test and select "Run checked tests"




10. The result will be shown as below:


Increasing the test result file storage limit in CodedUI

In CodedUI the Test Result folder is created automatically. The "Test Result" is in a folder in which the solution file is located(by default).

The default file storage limit is 25 files. The files are stored in .trx format which is nothing but an XML file.


We can increase the limit as described below in 5 steps:

1. Click on "Tools". Select "Options" menu item.



 

2. "Options" pop up will be shown. Click on "Test Tools" menu item from the list.
3.  Click on "Test execution" sub menu-item.




4. Enter the integer value i.e. the number of files you want to save in Test result folder.




5. If you want to see the detail reason (if script fails) on double click on test result we need to check the checkbox.



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.


Tuesday 8 July 2014

Customizing search properties while recording on internet explorer

This post explains the new “configurable properties" feature of the Coded UI test
Prior to VS Update 1, Coded UI Test records the controls with search properties and filter properties without any options of customization. For example, Recording a Mouse click on a button always generates the button with the same property list. Coded UI Test uses the search and filter properties to search for the control to complete the action during playback. However, Users might sometimes feel the need to customize the property list that Coded UI Test records because they have more knowledge of the controls than the Coded UI Test. For example, if we have a button whose text always changes, then there is no point in recording the “DisplayText” property and using it to search the button when it is unreliable.
With this update, Users will be able to customize the property list that gets recorded based on control type. You can configure the property list for each control type mentioned in the configuration.  If we change the property configuration of a Button, then all the subsequent recordings on any button control will record the properties as per the new configuration.
With this update, you can configure search and filter properties of HTML controls while recording on Internet Explorer.
Supported Versions:
  1. HTML5 controls require IE9 or latest. Progress bar and Slider HTML5 controls require IE10.
  2. All Visual Studio SKUs with Coded UI Test (with Internet Explorer recording) will get this feature on update:
                a. VS Ultimate
                b. VS Premium
                c. VS TestProfessional
                d. VSTF TestAgent
                e. VSTF TestController
Installation & Usage Experience:
  • Installation of the VS Update will install 2 files – an XML file (IEPropertyConfiguration.xml) and an XSD file (IEPropertyConfiguration.xsd) that validates the XML. These 2 files will be installed at “C:\Program Files\Common Files\Microsoft Shared\VSTT\11.0\” (x86 machine) or “C:\Program Files (x86)\Common Files\Microsoft Shared\VSTT\11.0\” (x64 machine).
  • This XML file is the configuration file that users should edit in order to configure the search properties. Users should use the XSD file to validate the XML after making any changes.
  • Configuration file is organized as a list of control types, each containing a list of search and filter properties. Users can edit the search/filter properties of any control type i.e. interchange properties between search and filter list or remove properties. Custom properties are not supported. If user changes the properties of a control type, then the subsequent recordings of that control will record using the updated property list.  Example:      
    <ControlType Name="Button">
     <SearchProperties>
     <Property Name="Id"/>
     <Property Name="Name"/>
     <Property Name="DisplayText"/>
     <Property Name="Type"/>
     </SearchProperties>
     <FilterProperties>
     <Property Name="Src"/>
     <Property Name="Title"/>
     <Property Name="Class"/>
     <Property Name="ControlDefinition"/>
     <Property Name="TagInstance"/>
     </FilterProperties>
    </ControlType>
  • In Addition, this configuration file also contains an attribute called “ApplySmartConfiguration” which can be set to true or false. This attribute’s behaviour is explained later in more detail. Example:  <ControlTypes ApplySmartConfiguration="true">

Usage Examples:
Once you change the configuration file, there is no need to rebuild or restart Visual Studio. You only need to restart your Coded UI Test Recorder/Builder to get the desired changes. Let’s take an InputButton for example and see how Coded UI test records differently with different configurations:


  1. Default configuration for InputButton (See the XML in previous section): properties will be recorded as per existing logic. All the properties configured are recorded.                                                                                                                                                                                                                                
  2. If you change your configuration for InputButton in IEPropertyConfiguration.xml to the below one. Then the recorded button will look like the below image. As you can see, Display Text and Control Definition are not recorded unlike the previous recording. (Note that “Src” is not recorded in both the scenarios. This property is for Image Buttons whose behavior is explained in the latter sections) :   
     <ControlType Name="InputButton">
     <SearchProperties>
     <Property Name="Id"/>
     <Property Name="Name"/>
     <!-- <Property Name="DisplayText"/> -->
     <Property Name="Type"/>
     </SearchProperties>
     <FilterProperties>
     <Property Name="Src"/>
     <Property Name="Title"/>
     <Property Name="Class"/>
     <!-- <Property Name="ControlDefinition"/> -->
     <Property Name="TagInstance"/>
     </FilterProperties>
     </ControlType>   
     
  3. Now we will interchange search and filter properties. As you can see from the image below, the recording is changed accordingly:                                                                     
     <ControlType Name="InputButton">
     <SearchProperties>
     <Property Name="Id"/>
     <Property Name="Name"/>
     <Property Name="Title"/>
     <Property Name="Type"/>
     </SearchProperties>
     <FilterProperties>
     <Property Name="Src"/>
     <Property Name="DisplayText"/> 
     <Property Name="Class"/>
     <Property Name="ControlDefinition"/> 
     <Property Name="TagInstance"/>
     </FilterProperties>
     </ControlType>  
     
     
Behaviour and Restrictions/Limitations:
  1. There are 2 restricted search properties which cannot be added to filter properties. These are “Id and Name”. Even if these properties are added to filter properties, it will have no effect on the generated code. One can remove these properties from the search properties but you cannot use them as filter properties. A warning will be logged in the trace log if these properties are configured as filter properties indicating the restriction.
  2. Custom properties are not supported. Users can only remove/re-add the properties present in the Configuration XML.
  3. Users can only configure the control types that are present in the configuration file. Adding any new control types manually will have no effect on the recorder generation for that control.
  4. Any parsing errors or invalid values in this configuration file will result in UITest falling back to original logic of property configuration for all control types. Unknown control types or parsing errors will create error log entries in trace log.
  5. At least one search property must be configured for any control type. If a control type is configured with zero search properties, then UITest will fall back to existing property configuration for that control type only.
  6. “ApplySmartConfiguration” attribute is added at the top most level in the configuration file. Default value is true. If the flag is set to true, then UITest will apply the smart logic on top of user configuration. If the flag is set to false, then UITest will not apply any additional logic i.e. final recording will look as it was configured in the xml.
ApplySmartConfiguration Attribute Usage and Behaviour:
Auto-Property Interchange:
  1. Prior to this update, if the ID and Name properties of a specific control have valid non-null values, then Coded UI Test will record ID and Name as Search properties and move all the other properties to filter properties for that control. If either ID or Name is NULL, then it will not move any search properties to filter properties. You can observe this behavior with your current builds or without changing the property configuration. So, if you have 2 buttons one with an ID and another without an ID, then you will see that there are more search properties recorded for the latter control whereas the former control will have only ID and Name as search properties.  In the below image, you can see that all the other properties are filter properties except Name and Id. If you go to earlier “Usage examples” section and check any recording, you will see that the ID is null and so Coded UI Test did not move any properties there.                                                                         
  2.  ApplySmartConfiguration - Set to True: Above logic is honored as usual irrespective of your property configuration in the XML.
  3.  ApplySmartConfiguration - Set to False: UITest will not do any property re-arrangement and will stick to the configuration provided. 
  4.  Example: Unlike the previous recordings in Usage Section, here the recording did not re-arrange the properties even though the ID and Name are both valid, when the flag is set to false:                                        
Conditional Property Additions (based on ApplySmartConfiguration flag):
  1. Some properties are not mandatory for some controls. For example, Image Button will have “Src” property whereas “Src” does not make sense for a normal Button. Coded UI Test validates some properties before adding them to the control. Sometimes, it is based on some of the control’s other property values. If the ApplySmartConfiguration flag is False, then Coded UI Test will not do any checks before adding the properties. If the flag is True, then the above Logic is honored before adding a property. If the validation fails, property will not be recorded.
  2. For all control types, ControlDefinition, Name and TagInstance property validations are common. ControlDefinition property will only be added if the children (descendant) count is less than 5000. Nameproperty will be added to all control types except “Body” control i.e. HtmlDocument. TagInstance will only be added if it is a valid number (i.e. > -1).
  3. Some Property specific validations are specific to control types. 
  4. Button/InputButton: “Src” property will only be added to button control, if it is an image button type. See the example image in the “Auto-Property Interchange” section. Here “Src” is added even though it is not an Image button because the flag is set to false.
  5. HyperLink:  InnerText property is added only for “Link” Nodes. Clickable area hyperlinks will not have InnerText property.
  6. Image:  Href and LinkAbsolutePath are added only if the image node is directly under an Anchor node, this check ensures that the image is a Hyperlinkimage.
  7. TableCell, TableRow:  MaxDepth is only added if the ID and Name are both null/empty for that cell/row control.

Tuesday 1 July 2014

Get the CodedUI test results into a specific folder or directory in organised way.


We can make the html logs getting displayed for checking or viewing the results of the Tests.
If we are using a TFS server, then its easy to view the results and logs. What if you do not have a TFS server and wanted to have your own custom application for viewing the results.

By considering this, I would like to share how to get all those results of a whole project into single folder with proper naming conventions.

Prior to it lets see how the existing html logs are stored
When each test is run, we see the file getting created on the following location

...\ Project Location \ TestResults \ Administrator \ In \ Some junk folder \ HYD-WIN7-XXX

For each test method in a codedUITest you see each new folder getting created and every html file getting saved with same name, which makes us hard to find which test method html file is it.

The method or the way i am making my results organised is
Creating a file or have a share location where the results are to be stored.
Create a folder with the name of your codedUI solution or even it can be done when u run ur tests i.e. its automated.
for each run of the Test method, i will be getting the name of the test and then pulling the file from the default location and placing it in the share location with the TestMethod name

Step 1

Define the directory or the share location and few variables

namespace CodedUITestProject1
{
    [CodedUITest]
    public class CodedUITest1
    {
        public static string TestResultDir;
        public static string MethodName;
        public static string ProjectName = Assembly.GetCallingAssembly().GetName().Name;
        public static string sFileName = string.Concat(@"C:\Results\", ProjectName + '\\' + DateTime.Today.ToString("MMddyyyy"), '\\', DateTime.Now.ToString("yyyyMMddHHmm"), "Result");
        public static Dictionary<string, string> ResultsKey = new Dictionary<string, string>();
        public CodedUITest1()
        {
            if (!Directory.Exists(sFileName))
            {
                Directory.CreateDirectory(sFileName);
            }
        }
     }
}

While defining the "sFileName" i am using timestamp so that i can keep the results organised in such  a way that i get all the results of test methods run at once in a single folder.

The dictionary item "ResultsKey" is used in storing the TestMethod name and also the directory in which the results will be created for that TestMethod 


Step 2

Declare the Dictionary in every TestMethod as follow

[TestMethod]

        public void CodedUITestMethod2()
        {
            ResultsKey.Add(MethodInfo.GetCurrentMethod().Name, Directory.GetCurrentDirectory());


Step 3

In the TestCleanup(), add the following code


[TestCleanup()]
        public void MyTestCleanup()
        {
            Dictionary<string, string>.KeyCollection keyColl = ResultsKey.Keys;
            foreach (KeyValuePair<string, string> kvp in ResultsKey)
            {
                UIMap.ResultsGen(kvp.Value, sFileName, kvp.Key);
            }
            ResultsKey.Clear();
         }


Step 4

Define the ResultsGen function which is used in the TestCleanup()

public static void ResultsGen(string SourceFilePath, string DestinationFilePath, string FileName)
        {
            if (FileName != null)
            {
                SourceFilePath = Regex.Split(SourceFilePath, "Out")[0] + "In";
                DirectoryInfo DirInfo = new DirectoryInfo(SourceFilePath);
                string finam = "";
                foreach (var fi in DirInfo.EnumerateFiles("*.html", SearchOption.AllDirectories))
                {
                    finam = finam + fi.Directory + '\\' + fi.Name;
                }
                File.Copy(finam, DestinationFilePath + '\\' + FileName + ".html");
                File.Delete(finam);
            }
        }


Step 5

This step has some additional information
To get the result of the Test method during runtime
use "TestContext.CurrentTestOutcome" in the TestCleanup()

To get the server name of the machine where the tests are rung
use "Dns.GetHostName()"



After following these steps, if the Tests are run, the results are seen as follow in a structured manner





Feel free to share if you got a better solution or you own way of storing results, which would help others