查看元素是否包含子元素的最快方法是什么?

时间:2016-11-02 08:14:04

标签: c# selenium selenium-webdriver

我有一个IWebElement(一个div),它包含一半的子元素。我想看看它是否包含子元素,如果是,我想捕获它。我做这样的事情:

IWebElement firstChild;
try 
{
    firstChild = divElement.FindElement(By.XPath("*"));
}
catch (NoSuchElementException e)
{
    // catch and handling...
}

但这有三个方面很慢:
1.使用By.XPath(" *")
2.如果元素不存在则缓慢的FindElement
3. try / catch是一种较慢的机制,我宁愿在项目的现有项上返回布尔值

如何加快检测子元素的速度?

修改
澄清一下:我正在执行的测试运行在带有div的网格上,典型的网格是4 x 16,所以64个字段。我想将此网格转换为DataTable以将其与预期结果进行比较。将这些字段捕获到数据表总共需要22秒。它的表现并不差,但我想刮掉那些宝贵的秒钟。

更新
我设法通过使用HTML Agility Pack捕获网格来实现。不幸的是(总有一些东西),input元素的值无法捕获,因为它们是动态设置的。作为一种解决方案,我让HAP返回输入元素的ID并使用FindElement(By.Id(inputId))捕获值,与其他Selenium选择方法相比,这是非常快的。

总而言之:我设法将捕获时间从大约22秒减少到不到3秒,性能提升超过600%。

2 个答案:

答案 0 :(得分:1)

您需要在XPath前添加.以在后代中进行搜索:

var elems = divElement.FindElements(By.XPath("(.//*)[1]"));
IWebElement firstChild = elems.Count > 0 ? elems[0] : null;

作为替代方案,您可以使用CSS选择器。它可能会稍快一些:

var elems = divElement.FindElements(By.CssSelector("*"));
IWebElement firstChild = elems.Count > 0 ? elems[0] : null;

答案 1 :(得分:1)

ISearchContext上创建一个扩展方法,如下所示:

public static IWebElement FindElementInstant(this ISearchContext context, By by)
{
    Driver.Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.Zero);

    var matchingElement = context.FindElements(by).FirstOrDefault();

    Driver.Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(/* whatever your implicit wait is normally */));

    return matchingElement;
}

用过:

var firstChild = divElement.FindElementInstant(By.XPath("*"));

如果您不需要访问匹配元素,则可以从bool返回FindElementInstant

暂时停用隐式等待,FindElements会立即返回空集合,如果不存在匹配元素,并且在FindElements内使用FindElement代替try-catch来自例外的额外时间。