Selenium - StaleElementReferenceException - 元素未附加到页面文档 (C#)
Selenium - StaleElementReferenceException - element is not attached to the page document (C#)
我很感激这个问题之前已经被问过很多次,但是当你觉得你已经尝试过 stack overflow 上发布的每一个解决方案时,那么是时候问一个问题了......
我在循环 table 并单击特定行中的链接时收到 StaleElementReferenceException
。第一次它运行良好,就在第一次迭代完成时出现错误。我完全明白这个错误想对我说什么,我只是不知道如何解决它:/
有问题的table如下:
与之相对应的HTML来源:
<table CLASS="datadisplaytable" SUMMARY="This table displays the components of the course." WIDTH = "100%"><caption class="captiontext">Components</caption>
<tr>
<td CLASS="ntheader" scope="col" >Description</td>
<td CLASS="ntheader" scope="col" >Weight </td>
<td CLASS="ntheader" scope="col" >Grade<br />Scale</td>
<td CLASS="ntheader" scope="col" >Must<br />Pass</td>
<td CLASS="ntheader" scope="col" style="display:NONE;" >Include in<br />Midterm or Final</td>
<td CLASS="ntheader" scope="col" >Incomplete<br />Scores</td>
<td CLASS="ntheader" scope="col" >Subcomponents</td>
</tr>
<tr>
<td CLASS="ntdefault">COURSEWORK - <a href="/pls/ubano1/BYLKEGRB.P_FacDispShrmrks?term=202210&crn=50493&gcom_id=322913">Portfolio of clinical learning - 2000 words</a></td>
<td CLASS="ntdefault">70/100</td>
<td CLASS="ntdefault">0-100 PG</td>
<td CLASS="ntdefault"><SPAN class="fieldmediumtext">Yes</SPAN></td>
<td CLASS="ntdefault" style="display:NONE;" >F</td>
<td CLASS="ntdefault">12</td>
<TD CLASS="ntdefault">
None
</TD>
<tr>
<td CLASS="ntdefault">PRACTICAL - <a href="/pls/ubano1/BYLKEGRB.P_FacDispShrmrks?term=202210&crn=50493&gcom_id=322914">Online Objective Structured Clinical Examination (OSCE) - 1 hour</a></td>
<td CLASS="ntdefault">30/100</td>
<td CLASS="ntdefault">0-100 PG</td>
<td CLASS="ntdefault"><SPAN class="fieldmediumtext">Yes</SPAN></td>
<td CLASS="ntdefault" style="display:NONE;" >F</td>
<td CLASS="ntdefault">13</td>
<TD CLASS="ntdefault">
None
</TD>
</tr>
</table>
<br />
<table CLASS="plaintable" SUMMARY="This table displays the links for composite information if applicable.">
<tr>
<td CLASS="pldefault"><a href="/pls/ubano1/BYLKEGRB.P_FacDispShrcmrk?term=202210&crn=50493&rectype_ind=F">View Final Composite Grades</a></td>
</table>
有问题的代码如下:
** 编辑 **
IWebElement dataDisplayTable = driver.FindElement(By.XPath("/html/body/div[4]/table[2]"));
List<IWebElement> dataDisplayTableRows = dataDisplayTable.FindElements(By.TagName("tr")).ToList();
foreach (IWebElement row in dataDisplayTableRows.Skip(1)) {
// Works first time round but then erros on 2nd iteration of loop
IWebElement assessmentTypeLink = row.FindElement(By.TagName("a"));
assessmentTypeLink.Click();
List<IWebElement> studentComponentListView =
GradebookCommon.getStudentComponentListView(row, driver);
foreach (IWebElement tr in studentComponentListView.Skip(2))
{
List<IWebElement> tableDataList = tr.FindElements(By.TagName("td")).ToList();
String studentId = tableDataList.ElementAt(1).Text;
if (Common.studentIdsMatch(studentIdToMatch, tableDataList, studentId))
{
driver.Manage().Window.Maximize();
IWebElement scoreColumnDiv = tableDataList.ElementAt(4);
IWebElement scoreColumnTextField = scoreColumnDiv.FindElement(By.TagName("input"));
scoreColumnTextField.SendKeys("60");
IWebElement submitBtn = driver.FindElement(By.XPath("/html/body/div[4]/form/input[8]"));
submitBtn.Click();
IWebElement selectComponentButton = driver.FindElement(By.LinkText("Select Component"));
selectComponentButton.Click();
break;
}
}
}
导致此问题的代码行是:
IWebElement assessmentTypeLink = row.FindElement(By.TagName("a"));
我尝试了其他几种解决方案,但每一种都没有成功。其中一些解决方案如下:
下面的解决方案只是循环了 x 次然后失败了。
public static bool clickAssessmentLink(By by, IWebDriver driver)
{
bool result = false;
int attempts = 0;
while (attempts == 0)
{
try
{
driver.FindElement(by).Click();
result = true;
break;
}
catch (StaleElementReferenceException e)
{
Console.WriteLine("Caught exception.. Retrying.");
}
attempts++;
}
return result;
}
我还尝试了以下方法(创建 WebElement 的副本):
来自这里:StaleReference
WebElement link = driver.findElement(By.TagName("a"));
link.click();
WebElement link1 = driver.findElement(By.TagName("a"));
link1.click();
我也试过
的 WebDriverWait
解决方案
public static void WaitAndClick(this IWebDriver driver, IWebElement webelement)
{
WebDriverWait fluentWait = new WebDriverWait(driver,TimeSpan.fromSeconds(20));
//No need to set PollingInterval, default is already 500ms
fluentWait.IgnoreExceptionTypes(typeof(NoSuchElementException));
fluentWait.Until(ExpectedConditions.ElementToBeClickable(webelement));
webelement.Click();
}
无论我求助于哪个解决方案,我都无法进一步解决。以前有没有其他人经历过这样的事情?我一定花了 15-16 多个小时来弄清楚这个问题!
在此先致谢,如有更多信息,请告诉我。
谢谢!
我已经通过以下方式解决了这个问题。这是否是最佳实践,我不太确定,但老实说,这是唯一对我有用的解决方案。我已经尝试了所有其他方法,但没有成功。
List<IWebElement> aHrefs = driver.FindElements(By.XPath("/html/body/div[4]/table[2]//a")).ToList();
List<String> links = new List<String>();
aHrefs.ForEach(link => { links.Add(link.GetAttribute("href")); });
foreach (String link in links) {
driver.Url = link;
Thread.Sleep(3000);
List<IWebElement> studentComponentListView = GradebookCommon.getStudentComponentListView(driver);
我所做的基本解释:
获取所有 <a>
标签并将它们保存在列表中(通过 XPATH)
List<IWebElement> aHrefs = driver.FindElements(By.XPath("/html/body/div[4]/table[2]//a")).ToList();
声明将保存 <a hrefs>
的新 List<String>
遍历每个 <a>
标签并获取 <href>
属性并存储在列表中
然后可以遍历 <href>
中的每个 link 并通过 driver.Url = link
打开它
我很感激这个问题之前已经被问过很多次,但是当你觉得你已经尝试过 stack overflow 上发布的每一个解决方案时,那么是时候问一个问题了......
我在循环 table 并单击特定行中的链接时收到 StaleElementReferenceException
。第一次它运行良好,就在第一次迭代完成时出现错误。我完全明白这个错误想对我说什么,我只是不知道如何解决它:/
有问题的table如下:
与之相对应的HTML来源:
<table CLASS="datadisplaytable" SUMMARY="This table displays the components of the course." WIDTH = "100%"><caption class="captiontext">Components</caption>
<tr>
<td CLASS="ntheader" scope="col" >Description</td>
<td CLASS="ntheader" scope="col" >Weight </td>
<td CLASS="ntheader" scope="col" >Grade<br />Scale</td>
<td CLASS="ntheader" scope="col" >Must<br />Pass</td>
<td CLASS="ntheader" scope="col" style="display:NONE;" >Include in<br />Midterm or Final</td>
<td CLASS="ntheader" scope="col" >Incomplete<br />Scores</td>
<td CLASS="ntheader" scope="col" >Subcomponents</td>
</tr>
<tr>
<td CLASS="ntdefault">COURSEWORK - <a href="/pls/ubano1/BYLKEGRB.P_FacDispShrmrks?term=202210&crn=50493&gcom_id=322913">Portfolio of clinical learning - 2000 words</a></td>
<td CLASS="ntdefault">70/100</td>
<td CLASS="ntdefault">0-100 PG</td>
<td CLASS="ntdefault"><SPAN class="fieldmediumtext">Yes</SPAN></td>
<td CLASS="ntdefault" style="display:NONE;" >F</td>
<td CLASS="ntdefault">12</td>
<TD CLASS="ntdefault">
None
</TD>
<tr>
<td CLASS="ntdefault">PRACTICAL - <a href="/pls/ubano1/BYLKEGRB.P_FacDispShrmrks?term=202210&crn=50493&gcom_id=322914">Online Objective Structured Clinical Examination (OSCE) - 1 hour</a></td>
<td CLASS="ntdefault">30/100</td>
<td CLASS="ntdefault">0-100 PG</td>
<td CLASS="ntdefault"><SPAN class="fieldmediumtext">Yes</SPAN></td>
<td CLASS="ntdefault" style="display:NONE;" >F</td>
<td CLASS="ntdefault">13</td>
<TD CLASS="ntdefault">
None
</TD>
</tr>
</table>
<br />
<table CLASS="plaintable" SUMMARY="This table displays the links for composite information if applicable.">
<tr>
<td CLASS="pldefault"><a href="/pls/ubano1/BYLKEGRB.P_FacDispShrcmrk?term=202210&crn=50493&rectype_ind=F">View Final Composite Grades</a></td>
</table>
有问题的代码如下:
** 编辑 **
IWebElement dataDisplayTable = driver.FindElement(By.XPath("/html/body/div[4]/table[2]"));
List<IWebElement> dataDisplayTableRows = dataDisplayTable.FindElements(By.TagName("tr")).ToList();
foreach (IWebElement row in dataDisplayTableRows.Skip(1)) {
// Works first time round but then erros on 2nd iteration of loop
IWebElement assessmentTypeLink = row.FindElement(By.TagName("a"));
assessmentTypeLink.Click();
List<IWebElement> studentComponentListView =
GradebookCommon.getStudentComponentListView(row, driver);
foreach (IWebElement tr in studentComponentListView.Skip(2))
{
List<IWebElement> tableDataList = tr.FindElements(By.TagName("td")).ToList();
String studentId = tableDataList.ElementAt(1).Text;
if (Common.studentIdsMatch(studentIdToMatch, tableDataList, studentId))
{
driver.Manage().Window.Maximize();
IWebElement scoreColumnDiv = tableDataList.ElementAt(4);
IWebElement scoreColumnTextField = scoreColumnDiv.FindElement(By.TagName("input"));
scoreColumnTextField.SendKeys("60");
IWebElement submitBtn = driver.FindElement(By.XPath("/html/body/div[4]/form/input[8]"));
submitBtn.Click();
IWebElement selectComponentButton = driver.FindElement(By.LinkText("Select Component"));
selectComponentButton.Click();
break;
}
}
}
导致此问题的代码行是:
IWebElement assessmentTypeLink = row.FindElement(By.TagName("a"));
我尝试了其他几种解决方案,但每一种都没有成功。其中一些解决方案如下:
下面的解决方案只是循环了 x 次然后失败了。
public static bool clickAssessmentLink(By by, IWebDriver driver)
{
bool result = false;
int attempts = 0;
while (attempts == 0)
{
try
{
driver.FindElement(by).Click();
result = true;
break;
}
catch (StaleElementReferenceException e)
{
Console.WriteLine("Caught exception.. Retrying.");
}
attempts++;
}
return result;
}
我还尝试了以下方法(创建 WebElement 的副本): 来自这里:StaleReference
WebElement link = driver.findElement(By.TagName("a"));
link.click();
WebElement link1 = driver.findElement(By.TagName("a"));
link1.click();
我也试过
WebDriverWait
解决方案
public static void WaitAndClick(this IWebDriver driver, IWebElement webelement)
{
WebDriverWait fluentWait = new WebDriverWait(driver,TimeSpan.fromSeconds(20));
//No need to set PollingInterval, default is already 500ms
fluentWait.IgnoreExceptionTypes(typeof(NoSuchElementException));
fluentWait.Until(ExpectedConditions.ElementToBeClickable(webelement));
webelement.Click();
}
无论我求助于哪个解决方案,我都无法进一步解决。以前有没有其他人经历过这样的事情?我一定花了 15-16 多个小时来弄清楚这个问题!
在此先致谢,如有更多信息,请告诉我。
谢谢!
我已经通过以下方式解决了这个问题。这是否是最佳实践,我不太确定,但老实说,这是唯一对我有用的解决方案。我已经尝试了所有其他方法,但没有成功。
List<IWebElement> aHrefs = driver.FindElements(By.XPath("/html/body/div[4]/table[2]//a")).ToList();
List<String> links = new List<String>();
aHrefs.ForEach(link => { links.Add(link.GetAttribute("href")); });
foreach (String link in links) {
driver.Url = link;
Thread.Sleep(3000);
List<IWebElement> studentComponentListView = GradebookCommon.getStudentComponentListView(driver);
我所做的基本解释:
获取所有 <a>
标签并将它们保存在列表中(通过 XPATH)
List<IWebElement> aHrefs = driver.FindElements(By.XPath("/html/body/div[4]/table[2]//a")).ToList();
声明将保存 <a hrefs>
List<String>
遍历每个 <a>
标签并获取 <href>
属性并存储在列表中
然后可以遍历 <href>
中的每个 link 并通过 driver.Url = link