cancel
Showing results for 
Search instead for 
Did you mean: 

Day 1 - API Testing vs. UI Testing

Contributor

Re: Day 1 - API Testing vs. UI Testing

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?

Occasional Contributor

Re: Day 1 - API Testing vs. UI Testing

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.

 

Delphi Code:

 

// 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[1] = '[' 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[0]);
      aTS.Delete(0);
      while (aTS.Count > 0) and
            (Node <> nil) do
      begin
        Node := FindChild(Node, aTS[0]);
        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.

Contributor

Re: Day 1 - API Testing vs. UI Testing

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. 

New Here?
Join us and watch the welcome video:
Watch the New Interview
APITestingMistake#2