Walkthrough: Using multiple Coded UI maps in test automation


This post will continue the previous post of Scaling up your CUIT UI automation for real world projects and walkthrough a sample test project using multiple UI maps.

For this walkthrough, I illustrate writing tests for an e-business website called TailSpin Toys that is an asp.net web application. The application is a regular shopping site that has different model planes for sale and users can login, view model plane details and purchase those that they are interested in.

The test project testing it contains 11 UI maps, each for different portions of the GUI. The test project is available for download here. I suggest readers download the code and look through as they read along the doc.

Since the application has several web pages and a number of user scenarios going through each of those pages, we structure our test project like this:

  • One UI map per each UI construct that can be treated separately. Eg: billing page, order details page, shopping cart etc.
  • Corresponding .cs and .designer.cs files for each UI map
  • One class called TestRunner in the testrunner.cs file that acts as a single point interface to all the test methods and contains instantiations of the UI maps
  • Tailspintestcase.cs file containing the test methods for each of the tests

clip_image002

The approach to writing test automation in this case will be slightly different from the one we use in our current Coded UI default model where you use the builder to record actions and add validations to compose the test. In this case, we will first create the building blocks in the form of different UI maps and then use those to compose a test method that acts on each of the different UI blocks.

To construct a UI map, just add a new Coded UI map from the “Add New Item” menu and open the coded UI test builder. Now, record actions on the desired UI or drag and drop controls using the cross hair. Once you are done with the operations on that particular UI component, generate code and save. As you navigate to a new UI component, again create a new UI map and load it into Coded UI builder and repeat the same process. In the Tailspin example, I create a UI map called “HomePage” and drag and drop controls like the different hyperlinks for plane options, hyperlink for cart etc. You can either record a set of actions or compose an action in the HomePage.cs file by creating a new method and adding actions on the controls captured inside the method. I’ve added a couple of navigate methods in the homepage UI map .cs file.

Once we have built all UI maps necessary for a scenario, we are now ready to start testing. In this case, my test scenario is a simple one – buy the “Contoso” Paper Model airplane in the site and ensure order receipt is delivered post billing. You can break this down into the following steps:

  1. Launch TailSpin
  2. Clean Up existing shopping cart items
  3. Go to “Paper Model” page
  4. Select “Contoso” plane
  5. Add it to the Shopping cart
  6. Go to shopping cart and proceed to check out
  7. Fill out billing and shipping details
  8. Verify you have order receipt

This scenario has to act on controls from different UI maps. Therefore, we need to instantiate the UI map objects for each of the controls to act on. To make the test method readable and easily maintainable, we add a utility class called test runner that contains properties per each UI map in the test project. When you add a new UI map, you just need to go add a new property in this class to access the instance of the UI map. In the test runner class, we add methods that are thin wrappers over the UI map’s methods containing the recorded actions. Eg: NavigateTopaperModel, SelectaPlane etc.

Now, in order to run this scenario, the test method only has to access the common utility class:

image

Likewise, we can compose more tests in different test classes, instantiate the utility class and act on different UI maps via the utility class object. Note that you could have very well skipped creating the utility class and directly instantiated each of the UI map objects in every test method and called them directly. That approach will also work, but the test code may look a bit more cluttered. Functionally, however the 2 approaches are equivalent.

Note that since we are testing a web application, the top level window, which will the browser displaying this web site, will be the common ancestor for all controls in the web site. Therefore, we will have at least one instance of the top level window control per each UI map. This leads to duplication of controls across maps, since there are 11 instances of the same top level window across the test project. To fix this, we use the CopyFrom() API to copy the TLW from the HomePage’s UI map into the TLW of each of the new UI maps. This API is called in each of the properties returning UI map instances so that during construction of the new UI map object, we equate the TLWs across all UI maps.

image

For a data driven test method, the only change would be to pass the desired values as parameters to the calling function in the utility class (which will in turn set the values in the parameters of the object passed into the method defined in the UI map) or directly pass to the UI Map objects themselves. For eg:

image

Comments (37)

  1. Sander says:

    Hello Anutthara,

    I’ve been trying to add all of the controls of a particular application to a UI Map, but this is proving to be fairly difficult and tedious. Sofar I’ve been manually finding every single control in the application and performing some kind of action or assert on it in order to get the control into the UI Map. Is there a faster or even automated way of mapping all of an application’s controls?

    Regards, Sander

    [Anu] Hi Sander – you don’t need to add validations to add controls to the UI map. Just drag the cross hair to the control you wish to add, press the “add control” button on the UI test builder (the first icon on the UI map) and it gets added to the map. It would be nice to have a single click that would capture all controls in a given UI – we might just do a power tool for that.

  2. daniel.falk@us.sogeti.com says:

    Hello Anutthara!  Thanks very much for this post! It is very thorough and informative!

    I have a question for you, if you don’t mind.  Given that you’ve broken up your CUI Test into mutliple Test Methods (something I’ve done myself), I’m wondering about what you’d suggest for error handling in this situation.

    I understand that VS2010’s default way of handling an error is to fail the current Test Method and then continue execution of the following Test Methods.  Have you ever found this problematic?  Left to its own devices, the rest of the Test would fall apart if a single Test Method fails, right?  So how would you suggest handling the event of a Test Method failure with regards to the remaining portion of the test?

    [Anu] Hi Dan – we deliberately do not allow the result of one test method to impact the other test method’s result. This is because tests are supposed to be independent of each other given we dont ensure order of execution. however, if you have tests dependent on the previous test’s result, you can easily deal with it by creating an ordered test with these test methods. That way, you have an option to choose that if one test fails, the other tests do not get executed

    Thanks very much!

    Dan

  3. Albert Hofmann says:

    Hi Anutthara,

    so you manually changed the files *.designer.cs? Wouldn’t any change to the UIMap lead to loss of the CopyFrom() API calls? This scenario doesn’t seem very unlikely as applications change quite often and so the tests have to change as well (adding new controls, removing unused controls, etc…)

    Any ideas how to avoid losing the CopyFrom() calls?

    Thanks

    Albert Hofmann

  4. Albert Hofmann says:

    Never mind. Just saw that the CopyFrom() statements are in testrunner.cs

    Sorry.

  5. yuxia says:

    Hi Anutthara!

    Very helpful artical.

    The CopyFrom method works well for applications have common top windows. But what can we do to handle common “sub windows”? In my application, we have many common tab pages shared by different windows. How can I avoid duplicating these shared “Low level window”?

    [Anu] In that case, I would recommend you have 2 top level windows per UI map and update both windows using the CopyFrom. You can reduce the tedium by eliminating other windows between top level window and low level window so that the number of windows to update are restricted to 2

  6. Hal says:

    How do you update the various UIMaps? Your description only talks about the initial recording of the 11 UIMaps. If you need to go back and update any of these maps, how do you select the one to work on? When I have launched the coded ui builder, I have not seen any way of selecting a specific map.

    [Anu] Good q, Hal. Just right click on the UIMap file you want to open and choose to open the file in Coded UI test builder. This will bring up the builder with your UIMap file loaded.

    thanks,

    Hal

  7. tanvirsidhu says:

    Hi Anu,

    Thanks for this informative post.

    My question is not related to multiple UIMaps but to how VS uses CopyFrom() API when adding objects to a single UIMap.

    Currently I have a problem where VS is creating multiple copies of parent objects and top level windows whenever I go back and record an interaction with a new object or just add the object to the UIMap. I realize that this is happening because  some parent object (or top level window) dynamic property has changed e.g. the Window Title, or the Login that I am using. Is there a way to tell VS to use CopyFrom in this case?

    Or do I have to manually add that code to UIMap.cs file and add calls to CopyFrom there?

    What would be the best way to go about this?

    Thanks,

    Tanvir

  8. rclukies says:

    Hi Anu,

    Thanks for this post, I have 1 question that I'm not getting on this.

    You state "This scenario has to act on controls from different UI maps. Therefore, we need to instantiate the UI map objects for each of the controls to act on."

    How do I go about creating that utilty class (TestRunner)?

    I have created all of my UI maps…but I don't know how to tie them into the 'main test'  .cs file.

    Thanks,

    Roger

    [Anu] Hi Roger – you just need to create the instantiations of your UI maps in the test method or the test class initialize method if you plan to use them across the class

  9. Neha says:

    I am getting an error "An item with the same key has already been added" when create a new coded UI test , before opening coded UI builder. I have reinstalled VS 2010 still the issue exists.

    Please give me a solution.

    [Anu] Neha – this is a known issue with multiple maps 🙁 The workaround is to create a new UI Map and continue working from there. Is this an acceptable workaround for you?

  10. Need help in using Separte UIMap.uitest file says:

    Hi,

    I have problem in accessing separte UIMap files.. Here is the info..

    1) I added a new folder "Screen1" under my Project (TerraScan)

    2) Then added new CodedUI test by right-clicking that 'Screen1' folder. —> Screen1TEST.cs

    3) Then added new CodedUI map item by right-clicking that 'Screen1' folder –> Screen1UIMap.uitest

    4) Then recorded some actions ,Generated Coded as "Method_AddScreen1". Here it created two files under "Screen1UIMap.uitest" – Screen1UIMap.cs and Screen1UIMap.Designer.cs

    5) Then came to 'Screen1TEST.cs' and added new [TESTMETHOD] and trying to call recorded method "Method_AddScreen1".

    Here i am unable to get "Screen1UIMap" UIMAP file under my project namespace.

    I am expecting  as

    Terrascan.Screen1UIMap.Method_AddScreen1();

    But under TerraScan this UIMAP file not listing…

    Can u give an idea… Anything i went wrong?

    [Anu] I'll need to see your code or the .uitest file along with the other classes. Can you please post this q on the MSDN forums for a quicker response?

    Thanks in advance

    Shanmugavel

  11. SHANMUGAVEL.C says:

    Hi anutthara,

    I need help on using separate UIMAP.uitest files… Here is my scenario.

    1) I have created a new folder "Screen1" under my project "TSApp".

    2) I added new CodedUI test by right-cliking "Screen1" folder –> "Screen1TEST.cs"

    3) then added new CodedUIMap item by right-cliking "Screen1" folder –> "Screen1UIMAP.uitest" and recorded some actions –> saved as "Method_Add". Here it created "Screen1UIMAP.cs" and "Screen1UIMAP.Designer.cs" files

    4) then i went to "Screen1TEST.cs" file and trying to call recorded "Method_Add" as

    TSApp.Screen1.Screen1UIMAP.Method_Add()

    but here it not listing out this "Screen1UIMAP" file under TSApp.Screen1..

    Anything i went wrong?  Can u give me an idea on this…OR

    Tell me the approach to use separate UIMAP file and creating TEST based on that…

    Thanks in advance,

    Shanmugavel.

  12. SHANMUGAVEL.C says:

    Hi,

    I need to make my TEST RESULT  to FAIL through my code after some conditions what i am expecting.

    How to code this?

    [Anu] You can use the TCM OM to do this. Look up MSDN help for more info. Search for string "TCM API"

    What method i have to use?

    thx…

    SCSVEL

  13. Matt says:

    Shanmugavel.c assert.fail("Message").

  14. nitro52 says:

    Hi Anu,

    After reading your guidance i have a few concerns about the scalability of CUIT. In the article you use a helper class to instantiate and get the correct UIMap for the section of the application you are testing. I can see how this is the best way to handle multiple UIMaps with the current system but it rases a few concerns.

    1. By doing this it requires you to reaproach the way you create recordings. You can no longer record via creating a new CodedUI Test and then selecting "Record actions, edit UI map or add assertions" because this will create and record into the UIMap.uitest (default)

    2. Recording needs to be done by right clicking the UItest file and select "Edit with Coded UI Test Builder". My biggest concern here is that Action recordings from MTM can no longer be converted into a CodedUI Test without recording every step. This goes against what makes MTM good, by converting manual tests into automated with ease.

    3. It drastically increases maintainability of the Coded UI tests as it requires a lot of restructuring  of any recorded tests just to be able to scale it.

    Is this correct? if it is our time spent on correctly designing tests in MTM would be better spent directly coding CUIT

    [Anu] Ryan – I'll follow up offline with you with a detailed response

  15. Nitin says:

    Hi Anu,

    Is it desirable to have only one UIMap.designer.cs file in a Solution or we can have multiple? The problem i am facing is when i create another UIMap.designer.cs file it gives error while comiling that methods or properties already exist in desiner.cs file?

    So what is the best recommendation for this?

    [Anu] Nitin – you can have multiple UI maps, but each will create it's own designer file – you don't need to explicitly create any designer.cs files

  16. sursharma says:

    Hi Anu,

    In Tailspin project we have UI Folder under which UIMaps are placed .

    1.We have to explicitly make UI Folder and create UI Maps in it .Is to make hierarchy only?

    2.How to create UI Map file explictly… is it from Add new Item>?(which item)?

    3.How to make UI Map Designer files explicitly? Arey they readonly tooo?

  17. RodneyK says:

    I am interested in your response to nitro52.  I too have the same concerns. Any way I could get from info from your offline discussion?

    [Anu] Hi Rodney – I just wrote a comment to Subbu saying our feature pack addresses a lot of Nitro's concerns. We are trying to put together more comprehensive docs around this. Meanwhile, the team blg post should help

  18. subbu@work says:

    Hi Anu,

    we are attempting to Automate functional tests for one of our web project, i ran through various blogs to understand what it take to scale up CUIT for big projects, i do agree with your demonstrations here but  i also stuck with similar thought like 'nitro52' had, can you please provide me your view on his comments, i also see provide your view on how Feature pack 2 can help us to scaling up CUIT

    [Anu] Hi Subbu – with the feature pack 2, we address a large part of nitro's concerns. Editing the UI test xml and parameterizing search queries etc. become pretty easy to do. Check out the post on our team blog at http://blogs.msdn.com/vstsqualitytools for more info on FP2. We are working on additional docs for CUIT – I don't have a release date for those yet 😉

    thanks

    subbu

  19. Nitro52 says:

    I would just like to add some comments on my experience with Feature Pack 2. Firstly the UIMap editor is a great start, It allows you to visually manage your UIMaps and makes it easy to Delete methods or move them from the UIMap (xml) to the code behind (c#/vb) for editing.

    However i found it still needs some improvements to be fully functional with Scalability. It does not fix one of the key aspects to scalability and that is managing multiple UIMaps. Converting an Action recording into a coded UI Test will always use a default UI Map with the name "UIMap.uitest" There is no way to change which UIMap it gets created in. To add to this there is no way to move the method/controls from the UIMap.uitest file into another UI Map, for example "GeneralUIMap.uitest". Due to these limitation it unfortunately means that you can not use Action recordings as templates from Test Manager and still have your Coded UI Tests Scalable

    [Anu] Thanks for the review, Ryan. I agree that we have not fixed scalability completely with this. We are trying to prioritize a bunch of backlog items, and unfortunately, this did not meet the bar for the FP

  20. CamB says:

    Hi Anu,

    I am working with a large app that I have built a bunch of UIMaps for. My issue is that the namespace being generated on these maps is too specific for my needs. Is there a way to change how this is generated?

    [Anu] Sorry Cam – AFAIK, there is no way to control that right now. Can you post this on the Coded UI forums as well just to confirm?

    Thanks,

    Cameron

  21. Rammohan says:

    Hi Anu,

    This information is really helpful for me. I have a question which is our framework requirement.

    Is it possible to call a coded UI test into other Coded UI test in same project.

    [Anu] Ram – yes, you can, but that's not advisable. You'd rather refactor into a function and call that function

    Thanks,

    Rammohan

  22. Allen Feinberg says:

    I can't seem to get the sample to work. The website sampletailspin.net/Tailspin.Web is no longer available and I can't seem to get the code to work with the VSTS 2010 ALM VM that Brian Keller just released. It makes it really hard to figure out multiple UI mapps when you guys don't have samples that work. How can I get the sample code to work on a machine where I have tailspin toys working?

    [Anu] Hi Allen – sorry for the late reply. Can you please write to me at anutthar @ microsoft dot com so I can have someone engage with you until your problem is resolved.

  23. Rich says:

    Anu,

    Your posts have been very helpful.  Thank you for sharing your knowledge and expertise with us.

    I have a large ASP.NET application that I need to test.  I have made a lot of progress, and much of the testing is data-driven.  But I have run into a problem that I'm hoping you could help out with.  

    On many pages, there are datagrids with multiple rows.  Each row has a column that would uniquely identify the row, and another column with a drop down list.  I want to be able to pass in the unique identifier to ID the row, then interact only with the row's drop down list.  I hope that makes sense.  I would appreciate any suggestions you may have.

    Thanks,

    Rich

    [Anu] Hi Rich – you can use the Instance property to uniquely identify the cells in the data grid. Note that this will mean your properties might have to change when the table gets reordered though

  24. Rich says:

    Hello Anu,

    When I record actions on a single web page document, why does generated code put some of the controls under a different parent window/document?  This is causing some of the controls to not be found during test execution.  I can move some of the code around in the designer class, but any changes I make there will be overwritten the next time I record something, won't they?  Am I doing something wrong?  Do you have any suggestions for working around this?  Thanks…

    [Anu] Rich – this is our current design in VS 2010. A good workaround would be to customize your search property using the UITest editor in FP2. Write to me for more details

     

  25. Doron says:

    Hello

    I walked in your way on my application . works fine,

    but,

    im trying now to add recording in one of the UIMap with the CUIT editor .

    after the recorded function added to uimap.designer.cs  , all the "old" function in TestRunner class are not recognized any more…

    can you help ?

    [Anu] Doron – what does "not recognized" mean? Can you not make calls to those functions?

  26. Kris says:

    I lik thi sapproach  However, the process of creating a UI map this way is really slow and laborious.  Is there way to get all the UI elements in a particula reagion automatically.

    [Anu] Kris – our APIs support doing this though we dont have a tool out of the box that would do this. I would love to see a community project around this.

  27. SMSBVT says:

    Where can I get resource links that shows me how to do data driven testing as you indicate above?

    [Anu] Try http://msdn.microsoft.com/en-us/library/ee624082.aspx

  28. Any says:

    Hello Anu,

    I would like you ask you a question about UI map.  Do we have any option that add something to UI map without record.  Right now, I just see we can rename or delete but not add something without using record.  Thanks

    [Anu] Unfortunately not – having a page maker sort of functionality would help – that could be a great project for a partner!

  29. Senthil says:

    Hi Anu,

    While trying to record the application VSTS2010 showing "Access Denied" message and the code was not generated.its displaying as below mentioned.could you assist us to solve this problems.

               // Access is denied.

               // The control for this action was not recorded.

               // The control for this action was not recorded.

               // The control for this action was not recorded.

               // The control for this action was not recorded.

               // The control for this action was not recorded.

               // The control for this action was not recorded.

               // Access is denied.

               // Access is denied.

               // Access is denied.

           }

    [Anu] Are you running the app as admin but VS as regular user?

  30. Nitro52 says:

    @Senthil

    UAC will cause this issue if MTM or Visual Studio is not running as administrator

  31. SDET says:

    Hi Anu

    I have a question about the updating the uitest file. After creating the UI elements in the uitest file, if I need to update the same to add new controls, what is the best approach?

    For ex: I got to a webpage and add some controls to the UIMap, the controls are added to the UI Map under a tree kind of view where Window being the root node. After some time, if I wish to edit the UI Map to have more controls, I edit the UI MAp using "Edit with Coded UI Test builder". However, The new controls get created under a different tree with another window being the root node. Now, both the windows have same name and it leads to lots of confusion. I am not sure, how the TestRunner should be configured to handle 2 or more windows with same name.

    Please advice.Thank You.

  32. Hi Anu,

    Thanks for the post! I tried to download the test project. Seems to be its not available. Could you please provide me the working link.

  33. Big Ian says:

    Hi Anu

    How do you add a recording to an existing UI Map in an Multi UI map coded UI?

    Regards

  34. Sreeya says:

    Hi Anu,

    The information posted by you is very helpful.Following your article i have created multiple UI Map files but not able to data drive. Could you please elaborate on how to apply data driven method.

    Thanks,

    Sreeya

  35. Jai says:

    Hi Anu,

    How can we select custom range in Data Driven Testing. Iteration property shows disabled for a Test. I read somewhere that this feature not supported. Can you please suggest any workaround?

  36. Kevin V says:

    I too tried to download the test project but it's not available. Can you provide a working link?

  37. Kevin Alder says:

    Where can I download the sample test project?