Searching for Test Objects

Applies to TestLeft 15.40, last modified on March 17, 2022

In tests, you often need to access an object that matches certain criteria. This topic describes how you can do this.

The Find and TryFind Methods

All test objects have the Find and TryFind methods. The methods have the following parameters:

  • The search pattern, which the sought-for test object must match.

  • The maximum level of the object hierarchy the search should reach.

The Find method returns the sought-for object if the search is successful, and fails if the object is not found. The TryFind method returns True and the sought-for object if the search is successful, and False and an empty object if the search fails.

The following example demonstrates how to find a button by its caption in the Replace dialog of the Notepad application:

C#

using SmartBear.TestLeft;
using SmartBear.TestLeft.TestObjects;
using SmartBear.TestLeft.TestObjects.Win;


[TestMethod]
public void Test()
{

  // Run Notepad and get the Notepad process
  IProcess notepad = Driver.Applications.Run("notepad");
  // Open the Replace dialog
  ITopLevelWindow wndNotepad = notepad.Find<ITopLevelWindow>(new WindowPattern()
  {
    WndClass = "Notepad"
  });
  wndNotepad.MainMenu.Click("Edit|Replace...");

  // Use the Find method to get the needed object
  IWinButton btnReplaceAll = notepad.Find<IWinButton>(new WindowPattern()
  {
    WndClass = "Button",
    WndCaption = "Replace &All"
  },
  3);
  // Simulate user actions over the found button
  …

  // Use the TryFind method to get the needed object
  IWinButton btnReplace;
  notepad.TryFind<IWinButton>(new WindowPattern()
  {
    WndClass = "Button",
    WndCaption = "&Replace"
  },
  3, out btnReplace);

  // If the object is found
  if (btnReplace != null)
  {
    // Simulate user actions over the found button
    …
  }

  …

}

Visual Basic .NET

Imports SmartBear.TestLeft
Imports SmartBear.TestLeft.TestObjects
Imports SmartBear.TestLeft.TestObjects.Win


<TestMethod()>
Public Sub Test()

  ' Run Notepad and get the Notepad process
  Dim notepad As IProcess = Driver.Applications.Run("notepad")
  ' Open the Replace dialog
  Dim wndNotepad As ITopLevelWindow = notepad.Find(Of ITopLevelWindow)(New WindowPattern() With {
      .WndClass = "Notepad"
    })
  wndNotepad.MainMenu.Click("Edit|Replace...")

  ' Use the Find method to get the needed object
  Dim btnReplaceAll As IWinButton = notepad.Find(Of IWinButton)(New WindowPattern() With {
      .WndClass = "Button",
      .WndCaption = "Replace &All"
    }, 3)
  ' Simulate user actions over the found button
  …

  ' Use the TryFind method to get the needed object
  Dim btnReplace As IWinButton
  notepad.TryFind(Of IWinButton)(New WindowPattern() With {
      .WndClass = "Button",
      .WndCaption = "&Replace"
    }, 3, btnReplace)

  ' If the object is found
  If btnReplace IsNot Nothing Then
    ' Simulate user actions over the found button
    …
  End If

End Sub

Java

import com.smartbear.testleft.*;
import com.smartbear.testleft.testobjects.*;
import com.smartbear.testleft.testobjects.win.*;
import com.smartbear.testleft.testobjects.WinFormsPattern;


@Test
public void Test() throws Exception{

  // Run Notepad and get the Notepad process
  TestProcess notepad = driver.getApplications().run("notepad");
  // Open the Replace dialog
  TopLevelWindow wndNotepad = notepad.find(TopLevelWindow.class, new WindowPattern() {{
    WndClass = "Notepad";
  }});
  wndNotepad.getMainMenu().click("Edit|Replace...");

  // Use the Find method to get the needed object
  WinButton btnReplaceAll = notepad.find(WinButton.class, new WindowPattern() {{
    WndClass = "Button";
    WndCaption = "Replace &All";
  }}, 3);
  // Simulate user actions over the found button
  …

  // Use the TryFind method to get the needed object
  WinButton btnReplace = (WinButton) notepad.tryFind(WinButton.class, new WindowPattern() {{
    WndClass = "Button";
    WndCaption = "&Replace";
  }}, 3).get();

  // If the object is found
  if (btnReplace != null)
  {
    // Simulate user actions over the found button
    …  }

}

The following example demonstrates how to find a link by its address on the main page of SmartBear Software’s web site:

C#

using SmartBear.TestLeft;
using SmartBear.TestLeft.TestObjects;
using SmartBear.TestLeft.TestObjects.Web;

[TestMethod]

public void Test()
{

  // Run the web browser and open the SmartBear Software home page
  IWebPage page = Driver.Applications.RunBrowser(BrowserType.IExplorer).ToUrl("https://smartbear.com/");

  // Use the Find method to get the needed object
  IWebElement link = page.Find<IWebElement>(new WebElementPattern()
  {
    ObjectType = "Link",
    href = "*testleft*"
  }, 15);
  // Simulate user actions over the found link
  …

  // Use the TryFind method to get the needed object
  page.TryFind<IWebElement>(new WebElementPattern()
  {
    ObjectType = "Link",
    href = "*testleft*"
  }, 15, out link);
  if (link != null)
  {
    // Simulate user actions over the found link
    …
  }

}

Visual Basic .NET

Imports SmartBear.TestLeft
Imports SmartBear.TestLeft.TestObjects
Imports SmartBear.TestLeft.TestObjects.Web


<TestMethod()>
Public Sub Test()
  ' Run the web browser and open the SmartBear Software home page
  Dim page As IWebPage = Driver.Applications.RunBrowser(BrowserType.IExplorer).ToUrl("https://smartbear.com/")

  ' Use the Find method to get the needed object
  Dim link As IWebElement = page.Find(Of IWebElement)(New WebElementPattern() With {
      .ObjectType = "Link",
      .href = "*testleft*"
    }, 15)
  ' Simulate user actions over the found link
  …

  ' Use the TryFind method to get the needed object
  page.TryFind(Of IWebElement)(New WebElementPattern() With {
      .ObjectType = "Link",
      .href = "*testleft*"
    }, 15, link)
  If link IsNot Nothing Then
    ' Simulate user actions over the found link
    …
  End If

End Sub

Java

import com.smartbear.testleft.*;
import com.smartbear.testleft.testobjects.*;
import com.smartbear.testleft.testobjects.web.*;


@Test
public void Test() throws Exception{

  // Run the web browser and open the SmartBear Software home page
  WebPage page = driver.getApplications().runBrowser(BrowserType.IExplorer).toUrl("https://smartbear.com/");

  // Use the Find method to get the needed object
  WebElement link = page.find(WebElement.class, new WebElementPattern() {{
    ObjectType = "Link";
    href = "*testleft*";
  }}, 15);
  // Simulate user actions over the found link
  …

  // Use the TryFind method to get the needed object
  link = (WebElement) page.tryFind(WebElement.class, new WebElementPattern() {{
    ObjectType = "Link";
    href = "*testleft*";
  }}, 15).get();
  if (link != null)
  {
    // Simulate user actions over the found link
    …
  }

}

The FindAll Method

The FindAll method searches for all the tested objects that match certain pattern and returns a sequence of all found objects.

If you use .NET, the returned sequence supports LINQ. You can use LINQ queries to sort test objects in the returned sequence, group them, filter them and so on. To learn more about LINQ and about using it to work with data, see the LINQ article in the MSDN Library.

If you use Java, you can use Lambda expressions to filter the returned sequence, sort items in it, and so on. To learn more about Lambda expressions in Java, see the Java documentation.

The following example demonstrates how to find all the buttons in the Replace dialog of the Notepad application and use LINQ queries and Lambda expressions to select only enabled buttons and sort them by their captions:

C#

using SmartBear.TestLeft;
using SmartBear.TestLeft.TestObjects;
using SmartBear.TestLeft.TestObjects.Win;


[TestMethod]
public void Test()
{
  // Run Notepad and get the Notepad process
  IProcess notepad = Driver.Applications.Run("notepad");
  // Open the Replace dialog
  ITopLevelWindow wndNotepad = notepad.Find<ITopLevelWindow>(new WindowPattern()
  {
    WndClass = "Notepad"
  });
  wndNotepad.MainMenu.Click("Edit|Replace...");
  ITopLevelWindow dlgReplace = notepad.Find<ITopLevelWindow>(new WindowPattern()
  {
    WndClass = "#32770",
    WndCaption = "Replace"
  });

  // Find all the buttons in the Replace dialog
  IEnumerable<IButton> buttons = dlgReplace.FindAll<IButton>(new WindowPattern()
  {
    WndClass = "Button"
  });

  // Select all visible buttons and sort them by their captions
  IEnumerable<IButton> visibleButtons = buttons.Where(b => b.Enabled).OrderBy(b => b.Cast<IWindow>().WndCaption);

  foreach (IButton button in visibleButtons)
  {
    // Simulate user actions over each button
    …
  }

}

Visual Basic .NET

Imports SmartBear.TestLeft
Imports SmartBear.TestLeft.TestObjects
Imports SmartBear.TestLeft.TestObjects.Win


<TestMethod()>
Public Sub Test()

  ' Run Notepad And get the Notepad process
  Dim notepad As IProcess = Driver.Applications.Run("notepad")
  ' Open the Replace dialog
  Dim wndNotepad As ITopLevelWindow = notepad.Find(Of ITopLevelWindow)(New WindowPattern() With {
      .WndClass = "Notepad"
    })
  wndNotepad.MainMenu.Click("Edit|Replace...")
  Dim dlgReplace As ITopLevelWindow = notepad.Find(Of ITopLevelWindow)(New WindowPattern() With {
      .WndClass = "#32770",
      .WndCaption = "Replace"
    })

  ' Find all the buttons in the Replace dialog
  Dim buttons As IEnumerable(Of IButton) = dlgReplace.FindAll(Of IButton)(New WindowPattern() With {
      .WndClass = "Button"
    })

  ' Select all visible buttons and sort them by their captions
  Dim visibleButtons As IEnumerable(Of IButton) = buttons.Where(Function(b) b.Enabled).OrderBy(Function(b) b.Cast(Of IWindow)().WndCaption)

  For Each button In visibleButtons
    ' Simulate user actions over each button
    …
  Next

End Sub

Java

import com.smartbear.testleft.*;
import com.smartbear.testleft.testobjects.*;
import com.smartbear.testleft.testobjects.Button;
import com.smartbear.testleft.testobjects.Window;


@Test
public Test() throws Exception{

  // Run Notepad And get the Notepad process
  TestProcess notepad = driver.getApplications().run("notepad");
  // Open the Replace dialog
  TopLevelWindow wndNotepad = notepad.find(TopLevelWindow.class, new WindowPattern() {{
    WndClass = "Notepad";
    }});
  wndNotepad.getMainMenu().click("Edit|Replace...");
  TopLevelWindow dlgReplace = notepad.find(TopLevelWindow.class, new WindowPattern() {{
    WndClass = "#32770";
    WndCaption = "Replace";
  }});

  // Find all the buttons in the Replace dialog
  List<Button> buttons = dlgReplace.findAll(Button.class, new WindowPattern() {{
    WndClass = "Button";
  }});

  // Select all visible buttons and sort them by their captions
  List<Button> visibleButtons = buttons.stream().filter(b -> {
    try {
      return b.getEnabled();
    } catch (Exception e) {
      return false;
    }
  }).collect(Collectors.toList());
  visibleButtons.sort( (Button b1, Button b2) ->
    {
      try {
        return ((Window) b1.cast(Window.class)).getWndCaption().compareTo( ((Window) b2.cast(Window.class)).getWndCaption() );
      } catch (Exception e) {
        return -1;
      }
    }
  );
  for (Button button : visibleButtons)
  {
    // Simulate user actions over each button
    …
  }

}

The following example demonstrates how to find all the links on the main page of SmartBear Software web site, use LINQ and Lambda expressions to select only the links that have “testleft” in their address and sort them by their text:

C#

using SmartBear.TestLeft;
using SmartBear.TestLeft.TestObjects;
using SmartBear.TestLeft.TestObjects.Web;


[TestMethod]
public void Test()
{
  // Run the web browser and open the SmartBear Software home page
  IWebPage page = Driver.Applications.RunBrowser(BrowserType.IExplorer).ToUrl("https://smartbear.com/");

  // Find all the links on the web page
  IEnumerable<IWebElement> links = page.FindAll<IWebElement>(new WebElementPattern()
  {
    ObjectType = "Link"
  }, 15);

  // Select all the links with the "testleft" string in their address and sort the links by their text
  links = links.Where(l => l.GetProperty<string>("href").Contains("testleft")).OrderBy(l => l.contentText);

  foreach (IWebElement link in links)
  {
    // Simulate user actions over each link
    …
  }

}

Visual Basic .NET

Imports SmartBear.TestLeft
Imports SmartBear.TestLeft.TestObjects
Imports SmartBear.TestLeft.TestObjects.Web


<TestMethod()>
Public Sub Test()
  ' Run the web browser and open the SmartBear Software home page
  Dim page As IWebPage = Driver.Applications.RunBrowser(BrowserType.IExplorer).ToUrl("https://smartbear.com/")

  ' Find all the links on the web page
  Dim links As IEnumerable(Of IWebElement) = page.FindAll(Of IWebElement)(New WebElementPattern() With {
      .ObjectType = "Link"
    }, 15)

  ' Select all the links with the "testleft" string in their address and sort the links by their text
  links = links.Where(Function(l) l.GetProperty(Of String)("href").Contains("testleft")).OrderBy(Function(l) l.contentText)

  For Each link In links
    ' Simulate user actions over each link
    …
  Next

End Sub

Java

import com.smartbear.testleft.*;
import com.smartbear.testleft.testobjects.*;
import com.smartbear.testleft.testobjects.web.*;


@Test
public void Test() throws Exception{

  // Run the web browser and open the SmartBear Software home page
  WebPage page = driver.getApplications().runBrowser(BrowserType.IExplorer).toUrl("https://smartbear.com/");

  // Find all the links on the web page
  List<WebElement> links = page.findAll(WebElement.class, new WebElementPattern() {{
    ObjectType = "Link";
  }}, 15);

  // Select all the links with the "testleft" string in their address and sort the links by their text
  links = links.stream().filter(l -> {
    try {
      return l.getProperty(String.class, "href").toString().contains("testleft");
    } catch (Exception e) {
      return false;
    }
  }).collect(Collectors.toList());
  links.sort( (WebElement l1, WebElement l2) -> {
    try {       return l1.getContentText().compareTo(l2.getContentText());
    } catch (Exception e) {
      return -1;
    }
  });

  for (WebElement link : links)
  {
    // Simulate user actions over each link
    …
  }
}

Troubleshoot Ambiguous Matches

There could be situations when several objects match the specified search criteria. In this case, by default, the Find and TryFind methods return an arbitrary found object. This may cause ambiguous recognition issues when a test will use an "inappropriate" object.

To detect ambiguous recognition issues, you can –

.NET: Set the IDriver.Options.Debug.RuntimeChecks property to AmbiguousMatches or to All.

Java: Call the driver.getOptions().getDebug().setRuntimeChecks method with the parameter set to RuntimeChecks.AmbiguousMatches or RuntimeChecks.All.

This will make TestLeft raise an exception when several objects match the criteria.

C#

using SmartBear.TestLeft;
using SmartBear.TestLeft.Options;


public void Test()
{

  // Perform additional checks during code execution
  Driver.Options.Debug.RuntimeChecks = Options.RuntimeChecks.AmbiguousMatches;

  // Obtain objects
  …

}

Visual Basic .NET

Imports SmartBear.TestLeft
Imports SmartBear.TestLeft.Options


Public Sub Test()

  ' Perform additional checks during code execution
  Driver.Options.Debug.RuntimeChecks = Options.RuntimeChecks.AmbiguousMatches

  ' Obtain objects
  …

End Sub

Java

import com.smartbear.testleft.*;
import com.smartbear.testleft.testobjects.*;
import com.smartbear.testleft.options.RuntimeChecks;


public void Test() throws Exception{

  // Perform additional checks during code execution
  driver.getOptions().getDebug().setRuntimeChecks(RuntimeChecks.AmbiguousMatches);

  // Obtain objects
  …

}

To fix the found ambiguous matches, you will need to adjust the search pattern so that it returns only the desired object. Most search patterns allow using a combination of properties to define the sought-for object. For example, to choose a particular process object from several similar processes, you can use a combination of ProcessName and Index properties. Besides, you can always add any custom property to the search pattern.

See Also

Creating TestLeft Tests
Understanding Object Identification
Verifying Object Properties

Highlight search results