首页 > 解决方案 > Selenium 不检索元素的当前文本值

问题描述

我正在使用 Selenium 和 ChromeDriver 在 C# 中编写一个测试应用程序。我有一个使用 AJAX 加载多个表的内容的网页,我的测试希望看到某个特定字符串加载到其中一个表中的某个位置。当我使用相同的参数手动进行测试时,我可以在屏幕上看到该字符串,但 Selenium 看不到它。

测试等待 jQuery 启动然后完成,然后查询表的文本值以查看是否有任何内容与测试字符串匹配。这就是问题所在:当它通过 innerHTML、innerText、textContent 和 value 属性或元素的 .Text 属性查询表的文本值时,它看不到通过 AJAX 加载的文本。它看到的原始表只是标题。所以看起来 Selenium 没有从页面中获取最新的值,AJAX 在 Selenium 获取之前没有完成,或者有其他问题。我怎样才能调试这个或更正确地编写我的查询?

对于我最初的调试工作,我首先验证是否选择了正确的表,并且 jQuery 确实开始和结束,然后像这样设置日志记录,所有这些行都会产生与初始标题类似的输出表格版本:

log.Trace(".Text: {0}", selectedElement.Text);
log.Trace("attr innerHTML: {0}", selectedElement.GetAttribute("innerHTML"));
log.Trace("attr innerText: {0}", selectedElement.GetAttribute("innerText"));
log.Trace("attr textContent: {0}", selectedElement.GetAttribute("textContent"));
log.Trace("attr value: {0}", selectedElement.GetAttribute("value"));

代码等待 jQuery 启动,然后通过它完成(从实际实现略微简化,它与对象的 ToString 进行比较并且在其他地方工作得很好):

string js = "return !!window.jQuery && window.jQuery.active == 0";
waiter.Until(_ => ((IJavaScriptExecutor)_).ExecuteScript(js)
    .ToString().Trim().ToUpper().Equals("FALSE"));
waiter.Until(_ => ((IJavaScriptExecutor)_).ExecuteScript(js)
    .ToString().Trim().ToUpper().Equals("TRUE"));

我现在唯一能想到的可能是该特定表的 AJAX 尚未处理但 jQuery 回来完成?这种可能性没有多大意义,但我不知道如何测试它来确定。

如果可能的话,我宁愿不修改站点本身,而是将所有与测试相关的部分保留在 C# 测试套件中。

编辑:我可以通过检查 Chrome 中的元素来查看值 - Inspector 中的 textContent 属性是正确的 - 但 Selenium 根本无法使用我当前的代码来获取它。由于 Selenium 每次都会选择其独特的标题文本,因此我可以毫无困难地选择表格本身。既然被问到了,这里是相关表格的净化版本,它深深地埋在页面中,并且有一个唯一的 ID,我用它来沿着 By.CssSelector("#thetable") 的行选择它:

<table id='thetable'>
  <colgroup> ... 5x <col> tags ... </colgroup>
  <thead>
    <tr> ... 5x <th> tags ... </tr>
    <tr> ... 5x <th> tags ... </tr>
    <tr><th colspan='5'...> ...</tr>
  </thead>
  <tbody>
    <tr> ... 5x <td> tags, one of which includes the text I look for ... </tr>
    ...
  </tbody>
</table>

前面提到的 table 元素本身的属性和属性只给了我来自 thead 部分的文本。

标签: c#seleniumselenium-webdriver

解决方案


如果您正在等待特定的文本,我建议等待文本而不是等待 Javascript 执行。

请参阅下面的代码:

public void TestWaitForText()
{
    IWait<IWebDriver> wait = new DefaultWait<IWebDriver>(driver);
    wait.Timeout = TimeSpan.FromSeconds(10);
    wait.PollingInterval = TimeSpan.FromMilliseconds(300);
    wait.Until(d => isAnyTextAppeared(d));
}

private Boolean isAnyTextAppeared(IWebDriver d)
{
    List<string> textList = new List<string>() { "foo", "bar" };
    foreach(var txt in textList)
    {
        var elems = d.FindElements(By.XPath("//tbody/tr/td[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'" + txt +"')]"));
        if (elems.Count > 0)
        {
            log.Trace(".Text: {0}", elems[0].Text);
            return true;
        }                    
    }
    return false;
}

推荐阅读