Build a Coded UI Test without a UI Map

So I ran into a customer recently that was getting pretty advanced with Coded UI and they were having trouble maintaining the UI Map technology as part of Visual Studio. One the things that I had noticed is that the UI Map does store lots of information including page names, URL’s and many other things that are interesting but not needed. This technology is great for beginners that need to get started with the technology.

So as I started thinking about it I was reflecting on some of the technologies that I have used before that included a way to search the DOM or Control Tree if you did not have an items mapped. Being a long time developer and avid Coded UI user I started thinking about how to solve this problem.

As I found quickly there are many ways solve this problem including taking the generated code from UI Map and move it around. It seems pretty simplistic under the covers but sure generates a LOT of code. J

As I started to think about how to condense the code and quickly .Net Generics came to mind. As I started this process I quickly started introducing the dynamic type and some of the cool things about the .Net Framework. So in the end I was left with a Custom Extension Method that extended the UITestControl class so that I could use it in line with my standard testing sequence. The code quickly became compact, readable and most of all it WORKED! I am always happy when those things align. I have included a snippet below of the TestMethod and also the static extension. You could also certainly use this with other web technologies since the base UI Testing framework uses UITestControl for all inherited types. So short story you can use the Class Extension for Windows, Web, WPF or any other automation controls that become part of Coded UI in the future.

Hope this helps someone else solve a very common problem.

 

Sample Test Method

[TestMethod]


public
void ThisIsATestUsingCalcWithNoUIMap()

{


//launch the application


var app = ApplicationUnderTest.Launch(“C:\\Windows\\System32\\calc.exe”, “%windir%\\System32\\calc.exe”);


//get all the controls we want to use – this uses dynamic types for serach and filter properties


WinWindow calWindow = app.SearchFor<WinWindow>(


/* pass search properties */
new { Name = “Calculator” },


/*pass filter properties if needed */
new { ClassName = “CalcFrame” });


WinButton buttonAdd = calWindow.Container.SearchFor<WinButton>(new { Name = “Add” });


WinButton buttonEqual = calWindow.Container.SearchFor<WinButton>(new { Name = “Equals” });


WinButton button1 = calWindow.Container.SearchFor<WinButton>(new { Name = “1″ });


WinButton button2 = calWindow.Container.SearchFor<WinButton>(new { Name = “2″ });


WinButton button3 = calWindow.Container.SearchFor<WinButton>(new { Name = “3″ });


WinText txtResult = calWindow.Container.SearchFor<WinText>(new { Name = “Result” });


//do all the operations


Mouse.Click(button2);


Mouse.Click(buttonAdd);


Mouse.Click(button3);


Mouse.Click(buttonEqual);


//evaluate the results


Assert.AreEqual(“5″, txtResult.DisplayText);


//close the application

app.Close();

}

 

 

Custom Extension Method

public
static
class
CodedUIExtension

{


public
static T SearchFor<T>(this
UITestControl _this, dynamic searchProperties, dynamic filterProperties = null) where T : UITestControl, new()

{

T ctrl = new T();

ctrl.Container = _this;


IEnumerable<string> propNames = ((object)searchProperties).GetPropertiesForObject();


foreach (var item in propNames)

{

ctrl.SearchProperties.Add(item, ((object)searchProperties).GetPropertyValue(item).ToString());

}


if (filterProperties != null)

{

propNames = ((object)filterProperties).GetPropertiesForObject();


foreach (var item in propNames)

{

ctrl.SearchProperties.Add(item, ((object)filterProperties).GetPropertyValue(item).ToString());

}

}


return ctrl as T;

}

 


private
static
IEnumerable<string> GetPropertiesForObject(this
object _this)

{


return (from x in _this.GetType().GetProperties() select x.Name).ToList();

}

 


private
static
object GetPropertyValue(this
object _this, string propName)

{


var prop = (from x in _this.GetType().GetProperties() where x.Name == propName select x).FirstOrDefault();


return prop.GetValue(_this);

}

 

}

Setting up Lab Management 2012 with an ISOLATED lab network

I was working with one of my customers to setup lab management with Microsoft Lab Management 2012 in an isolated lab scenario. All components of lab management including System Center Virtual Machine Manager and Controllers and agents are running in that isolated network. Everything was going smooth until we tried to create an environment using an already deployed virtual machine. Wasn’t as easy as I thought.

Problem

The problem with this scenario is that the isolated network poses some problems. We followed the guide located on MSDN (http://msdn.microsoft.com/en-us/library/ff652627.aspx) to open ports before we tried the first time. The guide was great and the ports were all setup as documented. All of the ports were opened between or regular network and the isolated network.

Once we got the port configuration in place we tried to setup the first environment with the already running virtual machine located on the isolated network. As you can see from the image on the left it was not too happy. It very quickly could not verify the machine and gave us an error that we could not get past. FYI – It also gave the same error for a standard environment.

Solution

As we started working with this the first place I started to look was the network protocols. We had the network administrator open all ports coming back to this machine from the isolated network. Next we installed Wireshark (http://www.wireshark.org/) to analyze the network traffic. The network traffic was normal and one-way into the lab until we got to this step for verification. On the verification step the target machines want to talk to our machine using the SMB protocol to pick up a configuration file.

After some DNS configuration and applying the network SMB protocol (port 445 à dynamic port) to come from the lab network back to the regular network the verification step was happy and we were able to proceed.

Hope this helps someone else with this scenario.