Today I was asked an interesting and challenging question regarding CodedUI. We are working on some code that a colleague of mine wanted to test with Spec flow and CodedUI. The challenge was that in the spec flow test they created an instance of some WFP UI components that are part of the application and they wanted to use CodedUI to validate the behavior. So this means the applciation under test is the test itself, since that is hosting the control.
So Why is this challenging, you might ask? Well there are a couple of things that will bite you when you try this and you need to get them solved first, hence my post to directly show you the solution 🙂
To simplify the scenario and show what you need to do, I created a simple test application that creates a Wpf Window. In this window I created 2 buttons. The first button is the button I will use to activate the CodedUI code (this is the spec flow code in our real life scenario) and one other button that CodedUI code will click after I clicked the “click Hello Automated” button. I called the second button “Hello”.
Here is a screenshot of the applciation:
Now to get started, You need to add quite some references to assemblies to get CodedUI to run within your application. Therese references don’t seem all to obvious, but without them, your code will crash at runtime with Assembly type load exceptions.
You need to reference the following set of assemblies: (I have them in the format, so you can copy and paste them straight into your csproj file, after unloading it in the ide, to save you some time)
<Reference Include=”Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=220.127.116.11, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL” />
<Reference Include=”Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL” />
<Reference Include=”Microsoft.VisualStudio.QualityTools.WindowsStore.CodedUITestFramework, Version=18.104.22.168, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL” />
<Reference Include=”Microsoft.VisualStudio.TestTools.UITest.Extension, Version=22.214.171.124, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL” />
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.TestTools.UITest.Framework.dll</HintPath>
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.TestTools.UITest.Playback.dll</HintPath>
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.TestTools.UITest.WindowsStoreUtility.dll</HintPath>
<Reference Include=”Microsoft.VisualStudio.TestTools.UITesting, Version=126.96.36.199, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL” />
Next we need to write some code to click the button.Since we are not part of a classic CodedUI test, we need to initialize the payback engine ourselves first. so therefore we start with a call the Playback.Initialize().
Next we need to find the application under test, and this is our own process. Therefore I used the environment class Process to get the current running process information and that we can pass to the ApplicationUnderTest and attach to it. With this we now have a search scope for all CodedUi controls we want to find. Then you create a WpfButton and pass it the search criteria how to find the button. I have done this by searching on the x:name property of the xaml control. Here is the code:
private static void ClickButtonViaCodedUI()
var proc = Process.GetCurrentProcess();
var app = ApplicationUnderTest.FromProcess(proc);
WpfButton btn = new WpfButton(app);
Now you normally would just call this method from the event handler of our button. But if you do this the code will not run properly. this has to do with the fact that the event handler of the button click that would activate our code, runs on the UI thread. CodedUI will create a “search” control that will then search for the UI control on the screen, but on the same UI thread that needs to receive the input of the mouse click. So we will block the UI thread until we would be done, blocking it from getting the codedUI input.
There is an easy fix for that, and that is to move the code to a background thread, enabling the UI thread to receive input.
So the event handler now looks as follows:
private void Button_Click(object sender, RoutedEventArgs e)
The final result now looks as follows:
You see me click the activation button, then coded UI will click the Hello Button and then the Message box pops up.
All in all not the most complicated code you have ever seen I think, but still there where at least two things that where less obvious I think. First to initialize the playback engine and second the threading issue. (besides finding all the assemblies you need to reference, which is an annoying and time consuming task :-))
Hope this helps!