Day 1 - API Testing vs. UI Testing
Hello TestComplete Community,
I’m happy to welcome you to our API Testing vs. UI Testing competition. We aren’t going to fight. We are going to identify what it is like - “Doing UI Testing”.
Each day, we will publish a new topic to discuss. Leave your comments in topics - you and your UI Team will be rewarded.
Today, let’s introduce ourselves to the Community! Post a high-level description of the project you are working on.
Leave your comments here.
UI Testing Score
Track the current score and daily conversations on this page:
Accomplish any of the bonus tasks to earn more points:
- +2 points - Invite your colleague to the competition.
Mention a nickname of this person by using @ in the competition’s daily topics. You can invite as many people as you wish. NOTE: A person you invite should be a new Community member registered after the event start.
- +2 points – Make a post on social media about your participation in the competition.
Your post should contain: @SmartBear, the #APIvsUITesting hashtag and the link to your comment in the Community.
- Leave your comments on a conversation of the day. 1 comment = 1 point to the team score.
- The competition will be held on March 25-29.
- Join the competition any day and participate in any daily conversations.
- Feel free to leave comments for any teams.
- Rewards! A team with the biggest score will win. Active participants from each team will be rewarded.
SmartBear Community and Education Manager
Hi @dpaulus , I'm also testing Delphi applications that use Virtual String Trees a lot and struggle with it. As of yet I have not been able to work out which Object Mapping on the project property to use in order to identify properties within the VST. When I use the object spy and select an VST object it returns the error "Error: An exception occurred: 0x0EEDFADE; class: EComponentError; description: 'TVirtualStringTree has not been registered as a COM class'" on the ComObject property. Are you able to share how you have been handling them?
Oh man - yeah, those are a pain. Currently, we ended up having our developers write a little function to do the dirty work for us (see code below), and then we call the function from our TC scripts as needed. I'm not a big fan of this method, and I did write a script that could handle it at one point, but it didn't work for every situation. I don't think this does either, but it's a bit easier to call. If you choose to use this, then you'd have to have your developer put it in their code (obviously, not ideal), and then call it from a debug version of the app your testing. Regarding your error, seems like there's a possible problem there, but a general idea here is to use the Object Browser, instead of Object Spy, because it'll give you a lot more detail about all the components, not just the one you highlighted. I almost exclusively use the Browser now when trying to lookup an object.
// Data can look like any of 'Value' or '[Value]' or '[Value][SubValue]' as many levels deep as needed. // The result they want back is |[n1]|[n2], etc. // where n1 is the node index of Value, // n2 is the child node index of SubValue, etc. // note the pipe. |[x] for each value returned. function TVirtualStringTree.GetNodeIndex(Data: String; VisibleColumnIndex: Integer): String; // for QA var Path: String; Column: Integer; function FindChild(aNode: PVirtualNode; aData: String): PVirtualNode; var Node: PVirtualNode; Idx: Integer; begin Result := nil; idx := -1; if aNode = nil then Node := GetFirst else Node := aNode.FirstChild; While Node <> nil do begin idx := idx + 1; if Text[Node, Column] = aData then begin Path := Path + '|[' + IntToStr(idx) + ']'; Result := Node; break; end; Node := Node.NextSibling; end; end; var lData: String; Node: PVirtualNode; aTS: TStringList; ColumnsArray: TColumnsArray; begin if Data <> '' then begin aTS := TStringList.Create; try ColumnsArray := Header.Columns.GetVisibleColumns; Column := ColumnsArray[VisibleColumnIndex].Position; Path := ''; lData := Data; if lData = '[' then lData := Copy(lData, 2, MAXINT); if lData[Length(lData)] = ']' then lData := Copy(lData, 1, Length(lData) - 1); aTS.Text := Trim(StringReplace(lData, '][', #13#10, [rfReplaceAll])); Node := FindChild(nil, aTS); aTS.Delete(0); while (aTS.Count > 0) and (Node <> nil) do begin Node := FindChild(Node, aTS); aTS.Delete(0); end; if Node <> nil then Result := Path else Result := ''; finally aTS.Free; end; end; end;
Not sure what language your scripts are in, but ours is in Python, and below is how it's called...
#----------------------------------------------------------------------------- # Process TVirutalStringTree #----------------------------------------------------------------------------- def Process_TVirtualStringTree(ItemObjStr, ItemValue): try: ColIndex = '0' # if '>' is found, split if ItemValue.find('>') != -1: ColName, ItemValue = ItemValue.split('>') # get list of column headers ColumnList = ItemObjStr + ".ContentToText(3,',')" ColumnList = eval(ColumnList) ColumnList = ColumnList.split(',') # loop through header list until value is found, then set index index = 0 index2 = 0 ColIndex = -1 for item in ColumnList: index = index + 1 item = item.strip() if item == ColName: ColIndex = str(index2) break index2 = index2 + 1 # if ColIndex is never updated, then the column was never found - log error if ColIndex == -1: Log.Error('Column not found') # pass column value and column index to John's routine NodeIndex = ItemObjStr + '.GetNodeIndex(' + '\'' + ItemValue + '\'' + ',' + ColIndex + ')' NodeIndex = eval(NodeIndex) # if john's routine returnes -1 then we log an error if NodeIndex == '': Log.Error(ItemValue + ' not found') ItemValue = NodeIndex return ItemValue except Exception as Error: TerminateDueToError('Process_TVirtualStringTree', str(Error))
Hope this helps.
Thanks for this. I use JScript for scripting but I'll discuss this with our Delphi developers and see if we can come up with a similar solution.