当前位置: 首页 > 知识库问答 >
问题:

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

宋涵衍
2023-03-14

我见过很多关于等待Selenium Web驱动程序(专门针对Java)的方法(比如这一个)。然而,应用这里的方法似乎并不奏效。

我试图通过在哈希表中的值中循环来测试用户查询结果。我在下面的代码中尝试了两种方法:等待Document.ReadyState和等待Class选择的项的加载。然而,看起来列表是在创建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);
  }
}

共有1个答案

辛建业
2023-03-14

如果您使用可重用性来编写代码,那么它将更容易理解,并且看起来不那么难看。尝试将可重用性缩小,然后将其组合起来以测试功能

 类似资料:
  • 我正在编写一个与我们的一个系统交互的硒脚本。在我们的系统中,有一个按钮,当按下时,它只能正确加载页面大约一半的时间(它只是在每隔一个场合加载无限长的时间),因此我不能依赖默认的硒等待页面加载。因此,我想按下按钮,并在打开新窗口之前立即关闭Web浏览器以继续执行脚本。不幸的是,我无法解决按钮本身的问题。 我目前的代码: 目前,System.out不太可能达到,因为一旦action.perform()

  • 正在研究尝试理解显式等待的方法。 所以单选按钮被点击后,输入形式发生了变化,所以我把给它一个时间元素出现,否则会出错“元素不可见......”。所以我认为现在是理解显式等待的好时机,因为我需要等到元素出现。 但出现错误“Selenium::WebDriver::error::ElementNotVisibleError:Element当前不可见,因此可能无法与之交互”。为什么这段代码不等到元素出现

  • 问题内容: 我正在使用bluebird,方法 getAll 和 update return promises。我如何说“等到两个承诺返回,然后更新currentProduct值”?我对JS很陌生… 问题答案: 如果可以使用/,这将很简单。 或者,如果您只能使用简单的承诺,则可以遍历所有产品,并将每个承诺置于最后一个循环中。这样,仅当前一个问题解决时,它才会前进到下一个问题(即使它将首先迭代整个循环

  • 本文向大家介绍JavaScript 异步等待循环,包括了JavaScript 异步等待循环的使用技巧和注意事项,需要的朋友参考一下 示例 在循环中使用异步等待时,您可能会遇到其中一些问题。 如果您只是尝试在内部使用await forEach,则会抛出Unexpected token错误。 这是因为您错误地将箭头功能视为一个块。该await会在回调函数,这是不是上下文async。 解释器可以防止我们

  • 问题内容: 我可以长时间等待Selenium Web Driver吗? 即使我可以像下面那样设置隐式等待命令,它也不会等待我给定的时间。 这里有什么问题吗? 就我而言,我需要执行一个测试用例并等待4分钟,然后执行下一个测试用例。 我在这里使用Java。 问题答案: 其实这不是我的答案,两天前我在这里看到了这个答案,但是我没有时间应用它。今天我尝试了,这就是我想要的。 不幸的是,现在我在这里看不到该

  • 问题内容: 我有一个使用mongodb本机驱动程序的node.js应用程序。在使用节点v8.9.1将应用程序代码迁移到异步/等待的过程中,我努力寻找一种适合mongodb查询的好方法。mongodb驱动程序的主要问题是,所有查询都使用回调,其中对异步方法来说,promise函数是必需的。 备择方案: 猫鼬 -承诺不赞成使用查询,它会强制使用Schema模型,这对我的应用程序来说有点开销。 mong