Tuesday 20 January 2015

Why does application close after each test in Coded UI Test


In Coded UI, a flag CloseOnPlaybackCleanup is added to ApplicationUnderTest class. 
For cases where an application is launched during test run, this flag helps determine whether to close the application under test after test is over.  Default value for the flag was set to true (closes the application) as it is not advisable to re-use resources from other test cases. 
This works fine for Visual Studio 2012 and later versions. Users will see  BrowserWindow / ApplicationUnderTest is getting closed after each test case if they don't have CloseOnPlaybackCleanup flag set to false. 
 If you want to reuse any application instance launched in another test case, you have to assign CloseOnPlaybackCleanup flag to false for ApplicationUnderTest / BrowserWindow object.
Please refer to sample code as below. If you run all these three tests together, BrowserWindow will be launched only once, remaining other tests will use existing browser instance from the previous test. If you run each test individually, then each test case will close the browser at the end of the run.

public class CodedUITest1
    {
        public CodedUITest1()
        {
        }

        [TestMethod]
        public void CodedUITestMethod1()
        {
           LoadLocalHost();
        }

        [TestMethod]
        public void CodedUITestMethod2()
        {
            LoadLocalHost();
        }

        [TestMethod]
        public void CodedUITestMethod3()
        {
            LoadLocalHost();
        }


        static BrowserWindow browserWindowInstance = null;

        public void LoadLocalHost()
        {
            if (browserWindowInstance == null)
            {
                browserWindowInstance = BrowserWindow.Launch(new System.Uri("http://google.com/"));
                browserWindowInstance.CloseOnPlaybackCleanup = false;
                browserWindowInstance.Maximized = !browserWindowInstance.Maximized;
            }
            else
            {
                browserWindowInstance.Maximized = !browserWindowInstance.Maximized;
            }
        }
}     

The same principle is applied with running tests using Command Line. If you are running tests altogether, the Application Under test will remain open in between tests in case CloseOnPlaybackCleanup is set to false. Once the run is over, all application instances which were launched during the run are closed.

Searching a UI Test Control with an invalid property


What if we give an invalid property as the Search/Filter property

For Web technology,
  • If an invalid SearchProperty is used to Find a UITestControl, it will throw UITestControlNotFoundException. 
e.g:- If you searched for the search edit box in google.com using a InvalidSearchProperty,
this.mUISearchEdit.SearchProperties["InvalidSearchProperty"] = "foo-bar";
you would get the UITestControlNotFoundException

  • If an invalid FilterProperty is used to Find a UITestControl, it will be ignored.
e.g:- If you searched for the search edit box in google.com using a InvalidFilterProperty,
this.mUISearchEdit.FilterProperties["InvalidFilterProperty"] = "foo-bar";
you would succeed in locating the edit box and performing operations performed on it.

For MSAA & UIA technologies,
  • If an invalid SearchProperty is used to Find a UITestControl, it will throw an ArgumentException
e.g:- If you searched for the button ‘6’ in the calculator using a InvalidSearchProperty
this.mUIItem6Button.SearchProperties["InvalidSearchProperty"] = "foo-bar";
you would get the following exception.
System.ArgumentException: The property InvalidSearchProperty is not a valid search property.
  • FilterProperties are not supported. If you specify FilterProperties for a WinForms or WPF control,  you will get the following message.
System.ArgumentException: Filter properties are not supported by the following technology: MSAA. To search for a control, you must remove the filter properties.
NOTE also for all technologies,
  • If an invalid Property is used in GetProperty/SetProperty, it will throw a NotSupportedException.

Monday 19 January 2015

How to add all controls on a page to the UIMap


This blog says how to add all controls on a page to the UI Map. This can be done with the following code.
Here I am adding all controls on the bing start page to the specified ui test file.

First create a UITest object from a file(i.e. empty UITest file).
You can add an empty UI Test file to your Test Project by right clicking on the Test Project and choosing Add –> New Item –> Coded UI Test Map.
UITest uiTest = UITest.Create(uiTestFileName);

The below 3 lines create a new UIMap object and adds it to UITest object
Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap newMap = new Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap();
newMap.Id = "UIMap";
uiTest.Maps.Add(newMap);

Now launch the browser, navigates to google.com and passes a reference to the browser & the UIMap object to GetAllChildren method. 
GetAllChildren(BrowserWindow.Launch(new Uri("http://bing.com")), uiTest.Maps[0];);
GetAllChildren is a method which recursively gets the children of the browser object and adds them to the UIMap.

The whole code

public void AddControlsToUIMap()
        {
string uiTestFileName = @"<LOCATION>\TestProject\UIMap.uitest";
UITest uiTest = UITest.Create(uiTestFileName);
Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap newMap = new Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap();
newMap.Id = "UIMap";
uiTest.Maps.Add(newMap);

GetAllChildren(BrowserWindow.Launch(new Uri("http://google.com/")), uiTest.Maps[0];);
             uiTest.Save(uiTestFileName);
        }

private void GetAllChildren(UITestControl uiTestControl, Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap map)
        {
foreach (UITestControl child in uiTestControl.GetChildren())
            {
                map.AddUIObject((IUITechnologyElement)child.GetProperty(UITestControl.PropertyNames.UITechnologyElement));
                GetAllChildren(child, map);
            }
        }

You can now customize the code based on your need. 

If you wanted to add the Childrens of specific type, instead of GetChildren, you can use FindMatchingControls