c# - 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 部分的文本。
解决方案
如果您正在等待特定的文本,我建议等待文本而不是等待 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;
}
推荐阅读
- c++ - 如何在 Qt C++ 中向自定义控件添加属性?
- php - 如何修改从市场安装的模块?
- python - 如何迭代数据框中的日期?
- ruby - 使用标准库 Ruby 标记数据以发送到 Elasticsearch 批量
- html - Angular:如果没有硬重新加载,Paypal 按钮不会出现两次
- javascript - 何时将文件命名为 JS 或 JSP?
- c - C - 如何运行一个线程几秒钟,然后继续第二个线程
- error-handling - 在 Clojure 中抛出要延迟的错误
- html - 当列的宽度小于 CSS 网格中的某个大小时,如何隐藏列?
- sap - 触发以更新表 SAP HANA 中的特定行