{"id":7381,"date":"2016-02-13T14:16:36","date_gmt":"2016-02-13T14:16:36","guid":{"rendered":"http:\/\/fluentbytes.com\/?p=7381"},"modified":"2016-02-13T14:16:36","modified_gmt":"2016-02-13T14:16:36","slug":"maintainable-test-automation-for-winforms-using-codedui","status":"publish","type":"post","link":"https:\/\/fluentbytes.com\/?p=7381","title":{"rendered":"Maintainable Test automation for Winforms using CodedUI"},"content":{"rendered":"<p>This week I got a request on <a href=\"https:\/\/twitter.com\/ahga4986\/status\/697432994626179072\">twitter <\/a>how to work with CodedUI for windows forms and if I had any example. A couple of weeks ago, during a deep dive session we did in Sweden, I got more or less the same question on how can I access my controls when using windows forms, because we are having trouble getting CodedUI to work for us. So therefore I thought it would be a good idea to create a simple sample and describe in a bit more detail how to approach this.<\/p>\n<p>If you have looked at my <a href=\"https:\/\/www.pluralsight.com\/search?q=marcel+de+vries&amp;categories=all\" target=\"_blank\" rel=\"noopener noreferrer\">PluralSight <\/a>courses or attended one of the training events where I teach CodedUI, you might know that I am trying to convince everyone to never use the CodedUI test recorder, since the way it tries to locate controls and the way it saves the information in the recording file is a nightmare to maintain.<\/p>\n<p>So when investigating how we can locate controls in windows forms in a maintainable way I also avoid the recorder and just use the CodedUI object model to find the controls I need. So let\u2019s first dive into how to find controls and then look at how to write maintainable UI Automation code.<\/p>\n<p><!--more--><\/p>\n<h2>So how can we locate controls in Windows forms applications?<\/h2>\n<p>First of all you need to search for controls by using the Search Control classes specific for Windows Forms applications. You will find these in the <b>Microsoft.VisualStudio.TestTools.UITesting.WinControls<\/b> namespace. You use the search properties on the control to define how CodedUI needs to search for the control.<\/p>\n<p>So let\u2019s have a look how we can locate different UI controls based on the following example application. Let\u2019s start with a Search for the button that is shown in the form here below?<\/p>\n<p><a href=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/clip_image001.jpg\"><img decoding=\"async\" loading=\"lazy\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image001\" src=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/clip_image001_thumb.jpg\" alt=\"clip_image001\" width=\"676\" height=\"418\" border=\"0\" \/><\/a><\/p>\n<p>First of all we need to know what the properties of this button are. If you look at how we develop windows forms applications then it is very common that the developer provides a name for the control in code, because they need to access them in code. You also see this button has a title \u201cClick me!\u201d<\/p>\n<p>The properties for this button look as follows:<\/p>\n<p><a href=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/clip_image002.png\"><img decoding=\"async\" loading=\"lazy\" style=\"background-image: none; float: left; padding-top: 0px; padding-left: 0px; margin: 0px 35px 0px 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image002\" src=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/clip_image002_thumb.png\" alt=\"clip_image002\" width=\"330\" height=\"536\" align=\"left\" border=\"0\" \/><\/a><\/p>\n<p>If you want to search for this control in a maintainable way, you always try to avoid taking any dependencies on the look and feel of the control you search for. So taking a dependency on the text on the button is generally not a smart thing to do. This would also cause issues when you have e.g. multi language versions of your application.<\/p>\n<p>So we want find the control preferably on the name the developer gave the control. Since that name will probably not change. Reason is that this name is also used in code for referring to the control.<\/p>\n<p>So we want to find the control based on the programmatic name. The question is, is this possible?<\/p>\n<p><a href=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/clip_image003.png\"><img decoding=\"async\" loading=\"lazy\" style=\"background-image: none; float: left; padding-top: 0px; padding-left: 0px; margin: 0px 34px 0px 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"clip_image003\" src=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/clip_image003_thumb.png\" alt=\"clip_image003\" width=\"297\" height=\"541\" align=\"left\" border=\"0\" \/><\/a><\/p>\n<p>To identify how to search for a control, you can use the test recorder tool to inspect the properties of the control when we run the application.<\/p>\n<p>The inspection of the control looks as shown in this screenshot on the side.<\/p>\n<p>Here you can see that we can search on the programmatic name of the control by using the search property Name of the control.<\/p>\n<p>So based on this information you would expect you would be able to find the control based on the following code:<\/p>\n<pre class=\"theme:vs2012 lang:c# decode:true\">[TestMethod]\npublic void ClickButton1()\n{\n  var app = ApplicationUnderTest.Launch(@\"WinformsCodedUI.exe\");\n  \/\/Find the Main Window\n  var mainWindow = new WinWindow(app);\n  mainWindow.WindowTitles.Add(\"Form1\");\n\n  \/\/Find the control that is a child of the Main Window\n  var button = new WinButton(mainWindow);\n  button.SearchProperties.Add(WinButton.PropertyNames.Name, \"Button1\");\n  Mouse.Click(button);\n}\n<\/pre>\n<p>But when you run this test you will see the test fails and is unable to locate the control.<\/p>\n<p>It took me a while to figure out, but apparently every control can be found by first searching for a WinWindow control that has the name of the control and then within that window search for the control.<\/p>\n<p>Normally I use a tool, called Spy++ to find controls in the UI. This tool has been in the C++ SDK for years and something I always used. But when you look with Spy++ you will see the control Hierarchy is the same as you would expect from the UI perspective.<\/p>\n<p>I got some help from <a href=\"https:\/\/social.msdn.microsoft.com\/profile\/abhitej_msft\" target=\"_blank\" rel=\"noopener noreferrer\">Abhitej John<\/a> who is a software engineer at Microsoft who works on the CodedUI tools. When I told him that I did not understand the hierarchy of the controls he told me the following:<\/p>\n<p><em>\u201cCoded UI for Windows forms works on IAcessible objects. The hierarchy that is defined by this native element (in coded UI terms) is what we use to search for controls. The tool that you would use in comparison to look at the hierarchy is \u201cinspect\u201d in MSAA mode. Spy++ is a UIA based tool that identifies WPF controls. Hence you see that difference in hierarchy\u201d<\/em><\/p>\n<p>So I used the tool he suggests that I could find on my machine at the following location:<br \/>\n<em><strong>&lt;install drive&gt;:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86\\Inspect.exe<\/strong><\/em><\/p>\n<p><a href=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/controlhierarchy.png\" rel=\"attachment wp-att-7481\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-7481\" src=\"https:\/\/www.fluentbytes.com\/wp-content\/uploads\/2016\/02\/controlhierarchy.png\" alt=\"controlhierarchy\" width=\"893\" height=\"462\" srcset=\"https:\/\/fluentbytes.com\/wp-content\/uploads\/2016\/02\/controlhierarchy.png 893w, https:\/\/fluentbytes.com\/wp-content\/uploads\/2016\/02\/controlhierarchy-300x155.png 300w, https:\/\/fluentbytes.com\/wp-content\/uploads\/2016\/02\/controlhierarchy-768x397.png 768w\" sizes=\"(max-width: 893px) 100vw, 893px\" \/><\/a><\/p>\n<p>When looking at the form using this tool you can see that when you set it in MSAA mode, you see the hierarchy is different and that is the reason we need to use a slightly different approach to find our controls.<\/p>\n<p>So that looks like follows for e.g. the button:<\/p>\n<pre class=\"theme:vs2012 lang:c# mark:10-12 decode:true\">[TestMethod]\npublic void ClickButton1()\n{\nvar app = ApplicationUnderTest.Launch(@\"WinformsCodedUI.exe\");\n\/\/Find the Main Window\nvar mainWindow = new WinWindow(app);\nmainWindow.WindowTitles.Add(\"Form1\");\n\n\/\/Find the control that is a child of the Main Window\nvar buttonWindow = new WinWindow(mainWindow);\nbuttonWindow.SearchProperties.Add(WinButton.PropertyNames.Name, \"Button1\"); \nvar button = new WinButton(buttonWindow);\nMouse.Click(button);\n}<\/pre>\n<p>This works for all the controls in the same way. You always search for a WinWindow that has the name of the control. then inside that window you search for the control of the type you expect.<\/p>\n<p>Now don\u2019t make the mistake I did to search inside the WinWindow for the control, including the search properties, because that will result in the dreadful message:<\/p>\n<p><em><strong><span style=\"color: #ff0000;\"><em>\u201cAnother control is blocking the control. Please make the blocked control visible and retry the action.\u201d<\/em> <\/span><\/strong><\/em><\/p>\n<h2>Alternatives with AccessibleName<\/h2>\n<p>An alternative way that also works is setting the AccessibleName of the control. if you set this value, then you don\u2019t need the containing WinWindow control and you can search straight for the control based on the name and the type you expect. But this has a nasty side effect that is probably not visible immediately.<\/p>\n<p>AccessibleName is used for accessibility tools. It provides the name of the control. You can check this by e.g. starting windows Narrator on your machine and the moment you click a control it will tell you which control you are accessing on that particular form. Now when we change the name of the accessible name, then we can introduce issues with our application in production when we have people that rely on these names to represent something they can understand.<\/p>\n<p>So therefore it is best to search based on the control name, without tweaking the AccessibleName property.<\/p>\n<h2>How can we make the test better maintainable?<\/h2>\n<p>As I have discussed in al my courses, the best way to ensure you create a maintainable set of UI Automation functions is by adopting the concept of writing DAMP tests. DAMP stands for Descriptive And Meaningful Phrases and you use this to ensure you can read the scenario from your tests straight from the code.<\/p>\n<p>You do this by abstracting the UI by using a Page Object Abstraction. For each functional part of your UI you create a class that abstracts the actions of the UI and provides methods you can call. Each method returns a Page Object that contains the next actions available in the UI. this then results in a nice Fluent API that you can use to write your test scenario.<\/p>\n<p>So for clicking all controls in the UI the test scenario would look like this:<\/p>\n<pre class=\"theme:vs2012 lang:default decode:true\">[TestMethod]\npublic void TestFormWithPageObject()\n{\n var app = ApplicationUnderTest.Launch(@\"WinformsCodedUI.exe\");\n MainForm frm = new MainForm(app);\n\n frm.SelectCheckboxOrrange()\n   .SelectItemInList(\"Green\")\n   .SelectRadiobuttonYes()\n   .SetTextboxText(\"Hello world\")\n   .ClickButton();\n}<\/pre>\n<p>I hope you agree that this is way more readable then the test I showed before, where I only clicked one button. Imagine the clutter you get when you click multiple elements in the test.<\/p>\n<h2>Page object pattern<\/h2>\n<p>So the way you write the methods in the Page Object abstraction is by creating a class MainForm and adding action methods in that class that interact with the UI as follows:<\/p>\n<pre class=\"theme:vs2012 lang:default decode:true \">public MainForm SelectCheckboxOrrange()\n{\n  var CheckboxOrange = FindCheckbox(\"Checkbox2\");\n  Mouse.Click(CheckboxOrange);\n\n  return this;\n}\n\nprivate WinCheckBox FindCheckbox(string controlName)\n{\n  var checkWindow = new WinWindow(testScope);\n  checkWindow.SearchProperties.Add(WinWindow.PropertyNames.ControlName, controlName);\n  return  new WinCheckBox(checkWindow);\n}<\/pre>\n<p>Now you see the actual search is now abstracted in the MainForm page class and my test now delegates the actual interaction with the controls to that instance of the class. By returning the MainForm instance as result of the method, you get the possibility to call the next method, resulting in the fluent API<\/p>\n<h2>Conclusion<\/h2>\n<p>We have looked at how to find controls in a windows forms application and found that we need to search for a WinWindow control first before we can find the actual control we want to interact with. Secondly I showed how you can abstract the interaction using a pattern called the Page Object Pattern, that enables us to write better maintainable code.<\/p>\n<p>You can download the full sample I have from this location: <a href=\"https:\/\/bit.ly\/MaintainableCodedUI\">https:\/\/bit.ly\/MaintainableCodedUI <\/a><\/p>\n<p>Just unzip it and run it in your visual studio IDE. The only thing you need to change is the launch path for the application, since that will be depending on where you unzipped the solution<\/p>\n<p>Hope this helps<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week I got a request on twitter how to work with CodedUI for windows forms and if I had any example. A couple of weeks ago, during a deep dive session we did in Sweden, I got more or less the same question on how can I access my controls when using windows forms, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[3,8],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fluentbytes.com\/index.php?rest_route=\/wp\/v2\/posts\/7381"}],"collection":[{"href":"https:\/\/fluentbytes.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fluentbytes.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fluentbytes.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/fluentbytes.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7381"}],"version-history":[{"count":0,"href":"https:\/\/fluentbytes.com\/index.php?rest_route=\/wp\/v2\/posts\/7381\/revisions"}],"wp:attachment":[{"href":"https:\/\/fluentbytes.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fluentbytes.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fluentbytes.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}