Selenium web驱动程序-循环内等待(Java)

我见过很多等待Selenium Web driver的方法(such as this one) (专门针对Java)。然而,在这里应用这些方法似乎不起作用。

我试图通过循环哈希表中的值来测试用户查询结果。我在下面的代码中尝试了两种方法:等待document.readyState和加载按类选择的项。然而,看起来列表似乎是在创建all,而没有为完成元素刷新留出时间。

package newproject;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;

import org.openqa.selenium.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
//import org.openqa.selenium.chrome.ChromeDriver;

public class MyClass {
  public static void main(String[] args) {
  System.setProperty("webdriver.gecko.driver", "/Users/niunani/Selenium/geckodriver");
  WebDriver driver = new FirefoxDriver();
  driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);

  String baseUrl = "https://www.zillow.com/san-diego-ca-92109/";

  //get price button and click
  WebElement priceButton = driver.findElement(By.id("price"));
  priceText = priceButton.getText();
  System.out.println(priceText);
  //priceButton.click();

  Map<String, List<String>> priceTestCases = new HashMap<String, List<String>>();

  List<String> threeHundThouSet = new ArrayList<String>();
  threeHundThouSet.add("400000");
  threeHundThouSet.add("500000");
  threeHundThouSet.add("600000");
  threeHundThouSet.add("700000");
  threeHundThouSet.add("800000");
  threeHundThouSet.add("900000");
  threeHundThouSet.add("1000000");

  List<String> fourHundThouSet = new ArrayList<String>();
  fourHundThouSet.add("500000");
  fourHundThouSet.add("600000");
  fourHundThouSet.add("700000");
  fourHundThouSet.add("800000");
  fourHundThouSet.add("900000");
  fourHundThouSet.add("1000000");

  List<String> fiveHundThouSet = new ArrayList<String>();
  fiveHundThouSet.add("600000");
  fiveHundThouSet.add("700000");
  fiveHundThouSet.add("800000");
  fiveHundThouSet.add("900000");
  fiveHundThouSet.add("1000000");

  priceTestCases.put("300000", threeHundThouSet);
  priceTestCases.put("400000", fourHundThouSet);
  priceTestCases.put("500000", fiveHundThouSet);

  WebElement priceExposedMin = driver.findElement(By.id("price-exposed-min"));

  WebElement priceExposedMax = driver.findElement(By.id("price-exposed-max"));

  WebElement priceDoneButton = driver.findElement(By.xpath("/html/body/div[1]/div[6]/div/div[1]/div[1]/div[2]/div[2]/div/div/div/button"));

  priceButton.click();
  for (Map.Entry<String, List<String>> entry : priceTestCases.entrySet()) {
      String key = entry.getKey();
      List<String> values = entry.getValue();
      System.out.println("Key = " + key);
      System.out.println("Values = " + values + "n");
      //priceExposedMin.clear();
      for (int i=0;i<20;i++) {
          priceExposedMin.sendKeys(Keys.BACK_SPACE);
      }
      priceExposedMin.sendKeys(key);
      for (String maxPrice : values) {
          System.out.println(maxPrice);
          //priceExposedMax.clear();
          //wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"price-exposed-max\"]"))).clear();
          for (int i=0;i<20;i++) {
              priceExposedMax.sendKeys(Keys.BACK_SPACE);
          }
          priceExposedMax.sendKeys(maxPrice);
          priceDoneButton.click();

          //ONE WAY: wait for document.readyState
          new WebDriverWait(driver, 30).until(
                  webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));

          //SECOND WAY: Wait for 30 sec until AJAX search load the content
          //new WebDriverWait(driver,30).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.className("list-card-price")));

          Integer countWrong = 0;
          List<WebElement> returnPrices = driver.findElements(By.className("list-card-price"));
          System.out.println(returnPrices);
          for (WebElement priceElement : returnPrices) {
              String priceString = priceElement.getText();
              priceString = priceString.replace("Est. $", "");
              priceString = priceString.replace("$", "");
              priceString = priceString.replace(",", "");
              Integer price = Integer.parseInt(priceString);
              if (price > Integer.parseInt(maxPrice)) {
                  countWrong++;
                  System.out.println("Over price : " + Integer.toString(price));
              }
              System.out.println("This price : " + Integer.toString(price));

          }
          System.out.println("Incorrect query result: " + Integer.toString(countWrong)) ;
          priceButton.click();
      }
  }

  }
}

我有时会遇到以下错误,这实际上可能是在元素更新时发生的。我正在寻找一个可以解决这个问题的解决方案:

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: The element reference of <div class="list-card-price"> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:25:48'
System info: host: 'Nhus-MacBook-Pro.local', ip: 'fe80:0:0:0:27:7d6f:961a:384a%en0', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.14', java.version: '1.8.0_221'
Driver info: org.openqa.selenium.firefox.FirefoxDriver
Capabilities {acceptInsecureCerts: true, browserName: firefox, browserVersion: 70.0.1, javascriptEnabled: true, moz:accessibilityChecks: false, moz:buildID: 20191030021342, moz:geckodriverVersion: 0.26.0, moz:headless: false, moz:processID: 9634, moz:profile: /var/folders/8c/whfw1mpd5tq..., moz:shutdownTimeout: 60000, moz:useNonSpecCompliantPointerOrigin: false, moz:webdriverClick: true, pageLoadStrategy: normal, platform: MAC, platformName: MAC, platformVersion: 18.0.0, rotatable: false, setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
Session ID: b93bceb8-123a-b546-8743-5c402cd8b341
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285)
    at org.openqa.selenium.remote.RemoteWebElement.isDisplayed(RemoteWebElement.java:326)
    at org.openqa.selenium.support.ui.ExpectedConditions$8.apply(ExpectedConditions.java:233)
    at org.openqa.selenium.support.ui.ExpectedConditions$8.apply(ExpectedConditions.java:228)
    at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:249)
    at newproject.MyClass.main(MyClass.java:110)

我目前的解决方法相当难看,可能会使测试花费的时间太长:

package newproject;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;

import org.openqa.selenium.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
//import org.openqa.selenium.chrome.ChromeDriver;

public class MyClass {
  public static void main(String[] args) {
  System.setProperty("webdriver.gecko.driver", "/Users/niunani/Selenium/geckodriver");
  WebDriver driver = new FirefoxDriver();
  driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);

  String baseUrl = "https://www.zillow.com/san-diego-ca-92109/";
  String tagName = "";
  String titleText = "";
  String priceText = "";

  //search title
  driver.get(baseUrl);
  WebElement searchTitle = driver.findElement(By.className("search-title"));
  tagName = searchTitle.getTagName();
  System.out.println(tagName);
  titleText = searchTitle.getText();
  System.out.println(titleText);

  //get price button and click
  WebElement priceButton = driver.findElement(By.id("price"));
  priceText = priceButton.getText();
  System.out.println(priceText);
  //priceButton.click();

  Map<String, List<String>> priceTestCases = new HashMap<String, List<String>>();

  List<String> threeHundThouSet = new ArrayList<String>();
  threeHundThouSet.add("400000");
  threeHundThouSet.add("500000");
  threeHundThouSet.add("600000");
  threeHundThouSet.add("700000");
  threeHundThouSet.add("800000");
  threeHundThouSet.add("900000");
  threeHundThouSet.add("1000000");

  List<String> fourHundThouSet = new ArrayList<String>();
  fourHundThouSet.add("500000");
  fourHundThouSet.add("600000");
  fourHundThouSet.add("700000");
  fourHundThouSet.add("800000");
  fourHundThouSet.add("900000");
  fourHundThouSet.add("1000000");

  List<String> fiveHundThouSet = new ArrayList<String>();
  fiveHundThouSet.add("600000");
  fiveHundThouSet.add("700000");
  fiveHundThouSet.add("800000");
  fiveHundThouSet.add("900000");
  fiveHundThouSet.add("1000000");

  priceTestCases.put("300000", threeHundThouSet);
  priceTestCases.put("400000", fourHundThouSet);
  priceTestCases.put("500000", fiveHundThouSet);

  WebElement priceExposedMin = driver.findElement(By.id("price-exposed-min"));
  //priceExposedMin.clear();
  //priceExposedMin.sendKeys("300000");

  WebElement priceExposedMax = driver.findElement(By.id("price-exposed-max"));
  //WebElement priceExposedMax = wait.until(
//        ExpectedConditions.visibilityOfElementLocated(By.id("price-exposed-max")));
  //WebElement priceExposedMax = new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(driver.findElement(By.id("price-exposed-max"))));
  //priceExposedMax.clear();
  //priceExposedMax.sendKeys("500000");

  WebElement priceDoneButton = driver.findElement(By.xpath("/html/body/div[1]/div[6]/div/div[1]/div[1]/div[2]/div[2]/div/div/div/button"));

  priceButton.click();
  for (Map.Entry<String, List<String>> entry : priceTestCases.entrySet()) {
      String key = entry.getKey();
      List<String> values = entry.getValue();
      System.out.println("Key = " + key);
      System.out.println("Values = " + values + "n");
      //priceExposedMin.clear();
      for (int i=0;i<20;i++) {
          priceExposedMin.sendKeys(Keys.BACK_SPACE);
      }
      priceExposedMin.sendKeys(key);
      for (String maxPrice : values) {
          System.out.println(maxPrice);
          //priceExposedMax.clear();
          //wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"price-exposed-max\"]"))).clear();
          for (int i=0;i<20;i++) {
              priceExposedMax.sendKeys(Keys.BACK_SPACE);
          }
          priceExposedMax.sendKeys(maxPrice);
          priceDoneButton.click();

          //wait for document.readyState
          //new WebDriverWait(driver, 30).until(
            //      webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));

          //Wait for 30 sec until AJAX search load the content
          new WebDriverWait(driver,30).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.className("list-card-price")));
          //new WebDriverWait(driver,30).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("ul > li.closed")));

          int timeToWait = 10; //second
          try {
              for (int i=0; i<timeToWait ; i++) {
                  Thread.sleep(2000);
              }
          } catch (InterruptedException ie)
          {
              Thread.currentThread().interrupt();
          }

          Integer countWrong = 0;

          boolean result = false;
          int attempts = 0;
          while (attempts < 2) {
              try {
                  List<WebElement> returnPrices = driver.findElements(By.className("list-card-price"));
                  System.out.println(returnPrices);
                  for (WebElement priceElement : returnPrices) {
                      String priceString = priceElement.getText();
                      priceString = priceString.replace("Est. $", "");
                      priceString = priceString.replace("$", "");
                      priceString = priceString.replace(",", "");
                      Integer price = Integer.parseInt(priceString);
                      if (price > Integer.parseInt(maxPrice)) {
                          countWrong++;
                          System.out.println("Over price : " + Integer.toString(price));
                      }
                      System.out.println("This price : " + Integer.toString(price));

                  }
                  System.out.println("Incorrect query result: " + Integer.toString(countWrong)) ;
                  priceButton.click();
                  result = true;
                  break;
              } catch(StaleElementReferenceException e) {
              }
              attempts++;
          }

      }
  }

  //driver.close();
  //System.exit(0);
  }
}

转载请注明出处:http://www.dbgszz.com/article/20230330/2143816.html