Automated Test Scripts - A Name Mapping User Story
Customer Guest Blog by Christian Ekiza
Some would say I am a lucky guy; I rarely need to maintain my automated test scripts. And when I do, it’s because there have been real, relevant changes in the application. Otherwise, my test scripts ALWAYS find the controls they are interacting with and run smoothly. It wasn’t always like that, though. I had my fair amount of quarrels with the “Object not found” errors. Until I learned how to best use the Name Mapping functionality with the application I was testing.
Developers Help Identify Controls for Automated Test Scripts
Sitting down with the developers, we used the Object Spy to figure out how deep into the application TestComplete could look. Then, we studied the different options we had to properly identify the controls. We discarded any caption, text or content based member since it would not be resilient to changes in the wording, lists, typos or localization. Also finding objects by their position was not a good idea, since our application runs in two different resolutions and it would cause problems if buttons were moved around the screen in later versions.
Of the few members that were left, a couple of them looked promising; ControlId and Id. However, looking into different versions of the app, we discarded the Id, since the same control had different values for this member in each build we had. Then we decided to stick with the ControlId, which presented a distinctive and constant value through the different builds, and we threw in the WndClass too, just to be safe. Sure there were a few objects (mainly popup dialogs) that required a different set of members to identify them, but there was no problem further than that and we found that the ClassName was enough to pin them down.
Name Mapping Templates Save Time
This, of course, was not the default NameMapping configuration that TestComplete used, so after a couple of times that I had to change and specify how to Identify the objects in the Object Name Mapping wizard, I thought that it was going to be a looong way to map the +1000 controls in the application. That’s when I found the Name Mapping Templates functionality. I created a set of templates of the kind ‘If the control I am mapping has WndClass=Button, then I want to auto-select WndClass and ControlID’. Much easier now!
But that wasn’t all; I found another feature that eased my work even more. It was painfully slow to have to drag the Map Object From Screen cursor every single time. So what I did instead was to select for mapping one of the controls that was deeper in the objects tree and let the Mapping wizard guide me down through all the parents for that object. Then, in the NameMapping screen, in the Mapped Objects panel, I chose the node for one of the parent objects for that control and right clicked on it to choose the Map Child Objects option. In this screen popup, I selected all the objects I was interested in mapping and proceeded to map them all, using the Highlight button to confirm the proper control was being mapped each time.
Refreshing Objects for Replicated Controls
With this and a proper naming convention for mapped objects (btnNameOfTheButton, dlgQuiteDescriptiveName, editYouCantMissThatOne, staticMeaningfulName, etc…) everything worked like a charm. Until I got the, “The specified mapping criteria do not provide unique identification of the object. This may cause recognition problems during the test run. Save the mapping settings?” warning. This control was of the same kind I had been using for a while and we couldn’t see any difference.
I will not enter in the details on why it was happening, but the bottom line is that there were places in the application in which some controls were replicated with similar properties. An example of this would be the Create/Edit/Delete/Close buttons, which were replicated within several tabs of a particular screen. All the Create buttons had the same ControlId, so did the Edit, Delete and Close. The only thing that made them different is that there could only be one of each VisibleOnScreen at the same time.
Ok then, when time came to map those buttons that did not have a unique ControlId, we added to the list of parameters used to identify them that they had to be Visible and VisibleOnScreen. Finally, since these particular controls could only be correctly identified and mapped when they appeared on screen, we had to make the association between the object and the mapping dynamically from the test scripts before using them. This we managed with the RefreshMappingInfo method that every mapped object has in TestComplete.
Depending on the use the scripts make of these controls, they refreshed the mapping right before starting to interact with them.
Or there are scripts to refresh all of the controversial controls in a particular area at once, usually invoked from within a routine that takes you to that particular screen. So, with the same call you make to navigate to a particular area it is ensured that, once visible, all the conflictive controls will have their mapping refreshed.
Finally, for some actions which were repeated over and over again we also had some simple subs that took care of these mapping issues for us.
This is how, with a good knowledge of the capabilities of the Object Mapping functionality and a few workarounds with the RefreshMappingInfo method, we fixed our mapping issues. Nowadays, we rarely need to maintain the Name Mapping, and when we do it’s mostly to map new controls.
SwQA Engineer at Systelab Technologies, S.A.
Chapter author in "Experiences of Test Automation" expected late 2011)