显式等待的java.lang.NullPointerException

时间:2018-01-11 04:09:08

标签: c# selenium remotewebdriver

我正在尝试循环并点击网页上的多个按钮。我的代码首先检查页面上元素的数量,然后循环并单击每个元素。

这适用于第一个循环,但后来我在第二个循环上遇到Element Not Found异常。这是因为当单击按钮时,元素将从页面中消失并且DOM会更改。然后我读到明确的等待将迫使Selenium重新生成DOM。所以我添加了明确的等待。

但现在我在java.lang.NullPointerException行的第一个循环上得到wait.Until

如果有任何不同,则驱动程序为RemoteWebDriver

var elements = new List<IWebElement>();
driver.Manage().Timeouts().ImplicitWait=TimeSpan.FromSeconds(0);
elements.AddRange(driver.FindElements(By.XPath("//button[contains(@data-cancelref,'outgoing_requests')]")));

if(!elements.Any()) {
    return;
}

int loop = elements.Count-1;
for(int i = 0; i<loop; i++) {
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
    wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//button[contains(@data-cancelref,'outgoing_requests')]")));
    var button = driver.FindElement(By.XPath("//button[contains(@data-cancelref,'outgoing_requests')]"));
    button.Click();
    Thread.Sleep(rnd.Next(2000, 4000));
}

driver.Manage().Timeouts().ImplicitWait=TimeSpan.FromSeconds(60);

堆栈追踪:

at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Remote.RemoteWebElement.get_Displayed()
at OpenQA.Selenium.Support.UI.ExpectedConditions.<>c__DisplayClass7_0.<ElementIsVisible>b__0(IWebDriver driver)
at OpenQA.Selenium.Support.UI.DefaultWait`1.Until[TResult](Func`2 condition)
at _Common.FDriver.Clean(IWebDriver driver, String prox, Int32 timeout, Boolean& success) in C:\_Common\FDriver.cs:line 727

第727行是For语句

1 个答案:

答案 0 :(得分:0)

我认为你让它变得比它需要的更复杂。根据您的说法,每次单击按钮,它都会从页面中消失。因此,您不需要(也不希望)使用计数器遍历元素,因为在每个循环中集合变小。

这是逻辑:

  1. 您抓取页面以获取当前的按钮集合
  2. 您点击第一个按钮
  3. 您重复这些步骤,直到没有其他按钮。

    IReadOnlyCollection<IWebElement> elements = GetElements();
    while (elements.Any())
    {
        elements.ElementAt(0).Click();
        elements = GetElements();
    }
    

    我把代码放在一个单独的函数中。你不必,但我认为它使代码更清洁。

    public IReadOnlyCollection<IWebElement> GetElements()
    {
        return new WebDriverWait(Driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.XPath("//button[contains(@data-cancelref,'outgoing_requests')]")));
    }