我已经看到许多等待Selenium Web驱动程序(特别是Java)的方法(such as this one)。但是,在此处应用这些方法似乎无效。
我试图通过遍历哈希表中的值来测试用户查询结果。我在下面的代码中尝试了两种方法:等待document.readyState和加载由类选择的项目。但是,似乎列表是全部创建的,没有留出时间完成元素刷新。
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",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,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);
}
}