Quickly finding all child elements
See original GitHub issueHello,
I recently discovered the WinAppDriver and have been attempting to create a GUI stress test using Appium that randomly clicks all elements in my application. I’ve hit a lot of snags along the way which I’ve worked around but this latest one I can’t seem to conquer.
I have successfully written code that recursively does the following:
- Click highest level element “e” and find all immediate children. -----2. Click first child of “e” and check if the child also has children. ----------3. If yes, continue recursively until no more children. ----------4. If no, return. -----5. Click second child of of element “e”.
etc.
The problem is that querying to see if an element has children is extremely slow. I manually construct my own xPath so that I know which element to search underneath (since there’s no way to get the xPath from an element otherwise) but even with the narrowed scope, it takes super long to find all children. We’re talking about 24 seconds.
My question is:
Is there a faster way to find all the children of an element? Or perhaps, any tips on achieving a GUI stress test another way? The app is a rather complex Windows Forms app that also has hosted WPF controls.
I’ve pasted the test code below for reference.
using TestApp.API;
using NUnit.Framework;
using System.Collections.Generic;
using OpenQA.Selenium.Appium;
namespace GuiAutomationTest
{
[TestFixture]
public class Program
{
DesktopSession desktopSession;
TestApp app;
public Program()
{
app = new TestApp();
app.Visible = true;
desktopSession = new DesktopSession();
}
[Test]
public void StartStress()
{
app.CreateNewProject();
string startingxPath = $"//";
var startingElement = desktopSession.DesktopSessionElement.FindElementByAccessibilityId("MainForm");
var window = desktopSession.DesktopSessionElement.CurrentWindowHandle;
RecursivelyClickAllElements(window, startingElement,startingxPath);
}
public void RecursivelyClickAllElements(string window, AppiumWebElement e, string xPath)
{
xPath += ConstructXPathFromElement(e);
System.Diagnostics.Debug.WriteLine($"Control: {e.GetAttribute("AutomationId")}; Displayed: {e.Displayed}");
//Check if the element is displayed (clickable) to avoid errors when clicking. An error occurs, for example, when attempting to click the selected item of a list box instead of the listbox itself.
if (e.Displayed)
e.Click();
//Grab the current window in case clicking the control changed the active window by popping up a dialog
string currentWindow = desktopSession.DesktopSessionElement.CurrentWindowHandle;
if (currentWindow != window)
{
//Need to write code to handle new dialog
}
//Find all immediate children under the current element
var childElements = desktopSession.DesktopSessionElement.FindElementsByXPath($"{xPath}*");
//If there are no children, abort and return back to parent element (if it exists)
if (childElements == null)
return;
else if (childElements.Count == 0)
return;
//If there are children, continue recursively down the chain
foreach (var element in childElements)
{
RecursivelyClickAllElements(currentWindow, element, xPath);
}
}
//Create an XPath based off of an elements attributes.
public string ConstructXPathFromElement(AppiumWebElement e)
{
string className = e.GetAttribute("LocalizedControlType");
className = (char.ToUpper(className[0]) + className.Substring(1));
string automationId = e.GetAttribute("AutomationId");
string name = e.GetAttribute("Name");
string xPath = $"{className}[@AutomationId=\"{automationId}\"][@Name=\"{name}\"]/";
return xPath;
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:12 (1 by maintainers)
Top GitHub Comments
@timotiusmargo ,
When can we expect the enhancement? I am seeing the same issue with our application. It will be really helpful if it is quicker
Regards, M. Ganesh
Thank you, this simple prefix helped me as well. I agree that this looks like a bug… I was calling WindowsElement.FindElementByXPath(“child:😗”) and it made no sense to get back the same element.