Selenium 2 StaleElementReferenceException при использовании DropDownList с AutoPostBack с InternetExplorerDriver - PullRequest
4 голосов
/ 25 февраля 2011

Я использую Selenium 2 для тестирования страницы веб-форм asp.net с использованием InternetExplorerDriver и обнаруживаю исключение StaleElementReferenceException.Страница содержит выпадающий список (авто-обратная передача), из которого я выбираю различные значения.

Пример кода:

Страница:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication.WebForm1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
  <head runat="server">
    <title></title>
  </head>
  <body>
    <form id="form1" runat="server">
    <div>
      <asp:DropDownList ID="ddl" runat="server" AutoPostBack="true">
        <asp:ListItem Text="one"></asp:ListItem>
        <asp:ListItem Text="two"></asp:ListItem>
      </asp:DropDownList>
    </div>
    </form>
  </body>
</html>

(Код-последний файл не содержит ничего, кроме автоматически созданного материала Visual Studio.)

Код тестового прибора:

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;

namespace IntegrationTests
{
  [TestFixture]
  public class WebForm1TestFixture
  {
    [Test]
    public void ShouldSelectItemOneThenItemTwo()
    {
      IWebDriver driver = new InternetExplorerDriver(); // Using ChromeDriver causes test to pass...
      driver.Navigate().GoToUrl("http://localhost/<my-virtual-directory-name>/WebForm1.aspx");
      IWebElement list = driver.FindElement(By.Id("ddl"));
      IWebElement itemOne = list.FindElement(By.XPath("option[1]"));
      itemOne.Select();
      list = driver.FindElement(By.Id("ddl"));
      IWebElement itemTwo = list.FindElement(By.XPath("option[2]"));
      itemTwo.Select();
      list = driver.FindElement(By.Id("ddl"));
      itemOne = list.FindElement(By.XPath("option[1]"));// This line causes the StaleElementReferenceException to occur
      itemOne.Select();

      // Some assertion would go here
    }
  }
}

При запуске теста появляется следующая ошибка:

OpenQA.Selenium.StaleElementReferenceException: Element is no longer valid
at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebDriver.cs: line 883
at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(DriverCommand driverCommandToExecute, Dictionary`2 parameters) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebDriver.cs: line 727
at OpenQA.Selenium.Remote.RemoteWebElement.FindElement(String mechanism, String value) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 570
at OpenQA.Selenium.Remote.RemoteWebElement.FindElementByXPath(String xpath) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 458
at OpenQA.Selenium.By.<>c__DisplayClasse.<XPath>b__c(ISearchContext context) in e:\Projects\WebDriver\trunk\common\src\csharp\webdriver-common\By.cs: line 119
at OpenQA.Selenium.By.FindElement(ISearchContext context) in e:\Projects\WebDriver\trunk\common\src\csharp\webdriver-common\By.cs: line 227
at OpenQA.Selenium.Remote.RemoteWebElement.FindElement(By by) in e:\Projects\WebDriver\trunk\remote\client\src\csharp\webdriver-remote-client\RemoteWebElement.cs: line 267
at IntegrationTests.WebForm1TestFixture.ShouldSelectItemOneThenItemTwo() in WebForm1TestFixture.cs: line 25 

Если я изменю тест на использование ChromeDriver, то тест пройден.Мне кажется, что это означает, что это либо проблема с InternetExplorerDriver, либо с самим браузером Internet Explorer.Кто-нибудь знает, что и если я могу что-то сделать, чтобы обойти это (сайт будет использоваться в IE конечными пользователями, поэтому, к сожалению, смена браузеров невозможна)?


РЕДАКТИРОВАТЬ: Текущий обходной путь, который я использую, должен поставить Thread.Sleep() после того, как список был выбран;это работает, но, очевидно, не идеальное решение.

Ответы [ 3 ]

3 голосов
/ 21 апреля 2011

Ниже приведен шаблон, который я в итоге реализовал.

После каждого item*.Select() я реализовал ожидание:

IWait<IWebDriver> wait = new MyCustomWebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(driver => <some-condition-to-wait-for>);

Где - это способ определения того, что выбор элемента завершен (например, путем проверки обновления другого элемента управления на странице, например,

wait.Until(driver => driver.FindElement(By.Id("someLabelId")).Text == "expectedValue")`.

MyCustomWebDriverWait - это класс, который реализует IWait<IWebDriver> и практически идентичен классу WebDriverWait , только он перехватывает StaleElementReferenceException и NotFoundException (что означало изменение типа * 1016). * от NotFoundException до WebDriverException.

Вы можете прочитать, как Даниэль Вагнер-Холл указал мне в этом направлении на группу пользователей Google Selenium здесь .

0 голосов
/ 21 января 2016

Я нашел звонок driver.refresh() после перехода на страницу, что он работал нормально, мой код:

        Pages.Login.Goto();
        Browser.Refresh(); <-- refresh the webdriver after going to the page
        Pages.Login.LogInAsRegularUser();
0 голосов
/ 30 марта 2011

Элемент списка может изменяться в DOM из-за автопостбэка. Попробуйте переопределить элемент списка каждый раз, когда вы выбираете опцию. Э.Г.

IWebElement itemOne = driver.FindElement(By.Id("ddl")).FindElement(By.XPath("option[1]"));
  itemOne.Select();
  IWebElement itemTwo = driver.FindElement(By.Id("ddl")).FindElement(By.XPath("option[1]"));
  itemTwo.Select();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...