Contributions
Re: Mapping FindChild object to Alias?
I've hada few of those too.. where Spreader name mapped to: Sys.Process("MyApp").WPFObject("HwndSource: root").WPFObject("root").WPFObject("ContentControl", "", 1).WPFObject("Grid", "", 1).WPFObject("SpreadGrid", "", 1) But thathas the same problem..even worse if they change one of the objects in between, it will break the mapping. Plus I have to remember at what midpoint this alias maps to. So I have to constantly look it up to build paths under it. Whereas: Set Spreader = Sys.Process("MyApp").FindChild("Name", "WPFObject(""SpreadGrid"", """", 1)", 9999) Never fails. I'd rather spend time making new tests, not maintaining old ones. Once I stopped using namemapping, I think I finally started to master TC2.9KViews0likes3CommentsRe: Mapping FindChild object to Alias?
Yea I don't do any webtesting yet so maybe WPFObjects are just faster to load than parsing the DOM on a webpage so that could be a factor. Also you may be right, i'm using ther "Automatically map objects and child objects" and that is likely why i get these ridiculous namemaps that are hard to maintain. I'll try just mapping the item with a single name. The biggest issue there is that unlike webpages where everything has a defined structure, wpfobject visually can have multiple layers that you can't physically see or click directly. For example, for a button... there is the "button" object which supports the "click" function. But on that there is the view, and the label and it's not as simple as just changing the button map by highlighting on screen and mapping.. often I have to traverse up a few levels of the parent to get the real button object that I can programmatically interact with. Additionally, this UI is stable but since it uses external objects like .NET and DevExpress, they constantly change "in-between" and that is out of our control which is likely why the find stuff works better for us.But I'll play a bit more with it and try your recommended mapping methods.1KViews0likes1CommentRe: Mapping FindChild object to Alias?
"I use FindChild quite a bit to patch up a broken automation until I can get around to fixing the name map" Exactly the problem! "Broken Automation due to namemapping". This is the problem we are avoiding. On Paper it sounds good.. and if your app is like Calculator where it all names itself nicely. Here's an example of a dev express control's Fullname: Sys.Process("MyApp").WPFObject("HwndSource: root").WPFObject("root").WPFObject("Grid", "", 1).WPFObject("FloatingContainerBorder").WPFObject("Grid", "", 1).WPFObject("FloatingContainerBody").WPFObject("border").WPFObject("Grid", "", 1).WPFObject("PART_ContainerContent").WPFObject("Grid", "", 1).WPFObject("DockPanel", "", 1).WPFObject("dockLayoutManager").WPFObject("spreadUserControlLayoutGroup").WPFObject("spreadUserControlLayoutPanel").WPFObject("DockPanel", "", 1).WPFObject("spreadLadder").WPFObject("gridControl").WPFObject("gridView").WPFObject("HierarchyPanel", "", 1).WPFObject("RowControl", "", 22).WPFObject("CellsControl", "", 1).WPFObject("LightweightCellEditor") Here's how it namemapped itself: Aliases.MyApp.Spread.root.Grid.FloatingContainerBorder.Grid.FloatingContainerBody.border.Grid.PART_ContainerContent.Grid.DockPanel.dockLayoutManager.spreadUserControlLayoutGroup.spreadUserControlLayoutPanel.DockPanel.PriceLadder.spreadLadder.gridView.HierarchyPanel.RowControl.CellsControl.LightWeightCellEditor Here's how it looks with FindChild: Sys.Process("MyApp").FindChild("Name", "WPFObject(""LightweightCellEditor"")", 99999) I'd take FindChild ANY DAY OF THE WEEK over the other two methods for multiple reasons... 1. It is much more readable and concise when sifting through code. It's insane to try to manage all those in-between objects. 2. When (not if) the grid object system (DevExpress in this case) gets updated, it ALWAYS changes the fullname somewhere in the middle. This in turn breaks the name mapping. Imagine now I have about 50 mapped items, and while some might figure themselves out when parents are fixed, most do not because the changes are later in the object string. With FindChild, I rarely need to change anything because it only care about the beginning and the end, the rest is dynamic. 3. It always gets the "latest" refresh on demand so if the properties have changed within the app, like color or data, it will automatically grap the latest data when I do the lookup. 4. There is surprisingly little to no performance difference between namemapping and doing live lookups. This shocked me the most and when I saw how fast it was I've never looked back. Namemapping is a no-go for our testing because of the extreme length of object names and volatility of the changes. One slight change anywhere in the fullname will break far too much. I am surprised this doesn't affect more people. Using my Accessor function above, I can simplify it more by giving a nickname to that FindChild call. In this case the obvious name could be "LightweightCellEditor". Granted that may be too generic as there will be other grids that will also have this name, but this was just an example. Usually for similar objects there is one identifying factor that makes it unique. For example, 2 buttons that are side by side: Set BuyButton = standaloneWindow.FindChild("NativeClrObject.Name", "buyButton", 999999) Set SellButton = standaloneWindow.FindChild("NativeClrObject.Name", "sellButton", 999999) Sometimes you even need multiple FindChild calls in one line as there may be 2 grids that use "gridControl" but somewhere in the middle, their parent wrapper is unique: Sys.Process("MyApp").FindChild("Name", "ordersUserControl", 9999).FindChild("Name", "WPFObject(""gridControl"")", 99999) Sys.Process("MyApp").FindChild("Name", "filledOrdersUserControl", 9999).FindChild("Name", "WPFObject(""gridControl"")", 99999) That is still much more plausible than the original fullname or name map.2.9KViews0likes5CommentsRe: Mapping FindChild object to Alias?
That is what he's getting at. He's trying to set a compile-time Alias equal to a run-time object and was looking for a way to do it. Unfortunately it cannot be done. Here's one method I use instead.... Instead of setting something at the beginning like Set CustomerGrid = Aliases.MyApp.MainWindow.root.ContentControl.Grid.FloatingContainer.Grid.FloatingContainerBody.border.customerPanel.dataListGrid Instead I create my own nickname for it and use my own accessor function that I call when I need to interact with "CustomerGrid" and completely get rid of Namemapping/Aliasing. Function TCGetObject (objName) MyApp =Sys.Process("MyApp").WPFObject("HwndSource: Shell", "*").FindChild("Name", "WPFObject(""HwndSource: standAloneWindow"")") Select Case objName Case "CustomerGrid" Set TCGetObject = MyApp.FindChild("Name", "customerGrid", 99999) Case "AddressGrid" Set TCGetObject = MyApp.FindChild("Name", "addressGrid", 99999) Case "SubmitButton" Set TCGetObject = MyApp.FindChild("Name", "buttonSubmit", 99999) Case "ClearForm" Set TCGetObject = MyApp.FindChild("Name", "buttonClear", 99999) Case Else msgbox "No object found with that name" Runner.Halt End Select End Function Then in my individual test calls, I simply pass the function as the object Sub Test1 Set CG = TCGetObject("CustomerGrid") CG.Click End Sub It doesn't solve the issue with being able to pre-define objects, but makes it a lotmore manageable and readable to use a more model-based object define that you'd call from within each test script. It also makes it completely dynamic in case the stuff in between changes, and it does all the time for my application. We use devexpress for our grids and UIs and it seems like each update changes the decorators and other layers. You could even add something like a WaitChild call within the case statement to wait for that object to exist. The only other alternative would be to do an init function that does a fly-by run through of all the menus first, and sets the objects as globals for use later. For example, if you are trying to test a popup in test 3 but that popup doesn't exist until you do test 1 and test 2, then you'd need to "fake" some data to get the popup active, then pop it up, set the globalized object, then delete all your fake data and start the real test. But this would be very inefficient.2.9KViews0likes8CommentsRe: Mapping FindChild object to Alias?
You are asking for the holy grail of namemapping. I asked for something along these lines as well and unfortunately neither at possible at this time making namemapping unusable for me. The problem you are encountering is that Aliases can point to objects that are not yet loaded but FindChild is an active lookup on an object at the time you call it.3KViews0likes10CommentsRe: Product change devexpress 12.1 to 14.2 script not run
Similar issues here. Updated to DevExpress 14.2 and now the method calls on grids like "ClickCell" or "HoverMouseCell" on my DevExpress.Xpf.Grid return a generic error and the test stops. Looks like the cell stuff needs some attention. Record/Playback only uses generic click(x,y) which is not feasible. An error occurred. Possible reasons: The application stopped responding. The application was compiled incorrectly (see the Open Applications topic in the help system). An error occurred in TestComplete. Technical information: 103 0x80020006 (Unknown name.) edit. Tested object: Sys.Process("TestApp").WPFObject("HwndSource: standAloneWindow").WPFObject("priceBookUserControl").WPFObject("DockPanel", "", 1).WPFObject("priceLadder").WPFObject("gridControl")867Views0likes0CommentsAutogenerate FindChild based name?
Is there a way (or can one be added) to generate a FindChild alternattive from the object spy? Here's the scenario... We have a .NET app with devexpress controls and TC works fine with all the controls, but this level of application has about 50 objects per name. Example: Set StatusMessage = Sys.Process("MyApp").WPFObject("HwndSource: root").WPFObject("root").WPFObject("ContentControl", "", 1).WPFObject("Grid", "", 1).WPFObject("Grid", "", 1).WPFObject("Part_WindowContent").WPFObject("Grid", "", 1).WPFObject("ContentControl", "", 1).WPFObject("PART_ContainerContent").WPFObject("barManager").WPFObject("DockPanel", "", 1).WPFObject("dockLayoutManager").WPFObject("mainLayoutGroup").WPFObject("statusMessagesLayoutPanel").WPFObject("statusMessagesGridControl") This is a pain to read and any slight change to the path will break it. I can use an Alias which comes out to: Set StatusMessage = Aliases.MyApp.AS3_MainWindow.root.ContentControl.Grid.Grid.ContentControl_1.Grid.ContentControl.PART_ContainerContent.barManager.dockLayoutManager.StatusGrid.statusMessagesGridControl But that's still a nightmare to read and when developers make small changes to the application, they often without knowing it will add additional adorner layers or groupboxes and they end up breaking the Alias. It also requires other QA coworkers to have the same Aliases setup on their machines which isn't practical. So the best way I've found is to use the FindChild method which then lets me shrink it down to: Set StatusMessage = Sys.Process("MyApp").FindChild("Name", "WPFObject(""statusMessagesGridControl"")", 99999) Ultimately this is the way to go for us. It is fully dynamic and saves us a lot of maintenance. The only problem is that I have to do all this manually by grabbing the fullname and then getting the first and last objects and putting the findchild in place. It would be ideal to have this show up as a field in the object spy Like Fullname: xxxxxx MappedName: yyyyyy FindChildMethod:Sys.Process("MyApp").FindChild("Name", "WPFObject(""statusMessagesGridControl"")", 99999) Is that or could that be possible?1.2KViews0likes2CommentsRe: Checking for existence of a Script Unit and functions/subs defined in it
Here it is converted to vbscript //VBScript Function FunctionExists (UnitName, FunctionName) Dim oTC, objRE, colFunctions, oFunc, objMatch set oTC = Sys.OleObject("TestComplete.TestCompleteApplication") Set objRE = New RegExp With objRE .Pattern = "\\([^\\]+).mds$" .IgnoreCase = True .Global = False End With If objRE.Test( Project.FileName ) Then Set objMatch = objRE.Execute( Project.FileName ) strProjectName = objMatch.Item(0).SubMatches(0) Else strProjectName = "" End If Set objRE = Nothing FunctionExists = false if (strProjectName <> "") Then set colFunctions = oTC.Integration.ProjectRoutinesIterator(strProjectName) colFunctions.Reset() while (colFunctions.HasNext()) set oFunc = colFunctions.Next if ((oFunc.UnitName = UnitName) AND (oFunc.Name = FunctionName)) then FunctionExists = true end if Wend End if End Function It should be noted that this checks for the existence of the unit/function as an added source unit to the project.As long as the the library is loaded in the project, it will show. even if you don't have it added to the executing code with USEUNIT. .. so that makes it somewhat limited in practical use. I don't know of a way to only check for the existing of loaded units in the active project at runtime.1.8KViews4likes0Comments