我正在使用Selenium和ChromeDriver用C#编写测试应用程序。我有一个网页,该网页使用AJAX加载了多个表的内容,而我的测试希望看到特定的字符串加载到这些表之一的某处。当我使用相同的参数手动执行测试时,可以在屏幕上看到字符串,但是Selenium看不到。
该测试等待jQuery启动然后完成,然后查询表的文本值以查看是否有任何内容与测试字符串匹配。这是问题所在:当它通过innerHTML,innerText,textContent和value属性或元素的.Text属性查询表的文本值时,看不到通过AJAX加载的文本。它看到原始表只是标题。因此,看起来Selenium未能从页面中获取最新的值,Selenium未能在获取AJAX之前就完成了操作,或者其他错误。我该如何调试或更正确地编写查询?
为了进行初步的调试工作,我首先验证了已选择了正确的表,并且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#测试套件中。
edit:我可以通过检查Chrome中的元素来看到这些值-Inspector中的textContent属性是正确的-但Selenium根本不会用我当前的代码来识别它。我很容易选择表本身,因为Selenium每次都会获取其唯一的标题文本。既然有人问过了,这里是该表的经过净化的版本,它已深深地埋在页面中,并且具有一个唯一的ID,我将使用该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部分的文本。
答案 0 :(得分:0)
如果您正在等待特定的文本,建议您等待文本而不是等待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;
}
答案 1 :(得分:0)
我设法解决了问题。
问题是,当您在 arraylist.add(new songs(ID[0], ...)); // didnt paste other variables
元素上查询那些文本属性时,它们会深入到table
元素中,然后在返回到thead
元素之前返回。这是我们网站上使用JS控制台可验证的浏览器。我不确定为什么会这样,也不确定我没有时间搜索这些信息,但是目前是这样。 (2018年7月7日,Chrome 67)
没有任何等待改变的行为。
解决方案是使用附加了tbody
的选择器,例如tbody
而不是.thetable tbody
,现在选择正确的文本。