FluentWait 无法正常工作:Youtube 示例
FluentWait Not Working Properly: Youtube Example
所以我之前让它工作,但我在我的代码中搞砸了一些东西,现在 FluentWait 方法似乎没有正确调用。如果我 运行 它使用 quickRun
设置为 false 它按预期工作(因为隐式)但是当我将它设置为 true 它不会因为它不会等待元素正确加载。有谁知道我做错了什么吗?
package myPackage;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
//import com.gargoylesoftware.htmlunit.javascript.host.Console;
//https://www.codeproject.com/articles/143430/test-your-web-application-s-ui-with-junit-and-sele
//this will open a dynamic page example (ie. youtube) trending
public class youtubeTest {
public boolean quickRun = false; //Disable for debugging otherwise full speed
private static int defaultDebugDelay = 2; //Time in sec for next test to occur in debug
//do no change any of the below
private String testUrl; //target url destination ie youtube
private WebDriver driver; //webdriver instance to reference within class
private int testIndex = 1; //initial index value for console outputting
public WebElement fluentWait(final By locator) {
Wait < WebDriver > wait = new FluentWait < WebDriver > (driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function < WebDriver, WebElement > () {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
});
return foo;
};
@
Before
public void beforeTest() {
driver = new SafariDriver();
System.out.println("Setting up Test...");
if (quickRun) {
System.out.println("Test Type: Quick Run (Fastest Mode)");
} else {
System.out.println("Test Type: Slow Run (Debug Mode) - Each Test has a " + defaultDebugDelay + " sec call time buffer");
}
testUrl = "https://www.youtube.com";
driver.get(testUrl);
System.out.println("Setting Driver " + driver + "for url: " + testUrl);
}
@
Test
public void Test() {
//insert unit tests within here
//open yt nav menu
locateClickableElement("#appbar-guide-button");
//go to trending
locateClickableElement("#trending-guide-item");
//click on 4th Trending video from list
//locateClickableElement(".expanded-shelf-content-item-wrapper", 3);
locateClickableElement(".expanded-shelf-content-item-wrapper");
}
@
After
public void afterTest() throws Exception {
//wait 10 sec before closing test indefinitely
System.out.println("Test auto ending in 10 seconds...");
Thread.sleep(10000);
stopTest();
}
//individual unit tests
private void locateClickableElement(String ExpectedElement, int child) {
//format string into something like: "ELEMENT:nth-child(1)"
String formattedString = ExpectedElement + ":nth-child(" + child + ")";
System.out.println("Strung: " + formattedString);
locateClickableElement(formattedString);
}
private void locateClickableElement(String ExpectedElement) {
try {
System.out.println("Test " + testIndex + ": locateClickableElement(" + ExpectedElement + ")");
//do absolute delay for visual debugging
if (!quickRun) Thread.sleep(2000);
//click on target if found
fluentWait(By.cssSelector(ExpectedElement)).click();
System.out.println("Test " + testIndex + ": Successful Click on Element(" + ExpectedElement + ")");
} catch (Exception e) {
//whenever error is found output it and end program
System.out.println("Error Could not locateClickableElement(" + ExpectedElement + ")");
System.out.println("Exception Handled:" + e.getMessage());
stopTest("error");
}
testIndex++;
}
private void stopTest() {
System.out.println("Test Completed: Reached End.");
driver.quit();
}
private void stopTest(String typeError) {
System.out.println("Test Completed: With an Error.");
driver.quit();
}
}
我会以不同的方式写这篇文章并提供一些建议。
不要使用 "debug mode" 减慢测试速度。如果您想调试您的测试,请使用断点并单步执行代码以查看它是如何工作的。
这里不需要FluentWait
。使用 ExpectedConditions.elementToBeClickable(locator)
的简单 WebDriverWait
就可以很好地工作并且不那么复杂。如果您接受我的更改,您甚至不需要它。
不要使用 String
传递定位器,使用预期的定位器 class、By
。您无需对其进行解释、翻译等操作,而且速度更快、更灵活。
除非您正在尝试测试 UI(我假设您不为 youtube 工作),否则您可以使用 Trending link 在页面顶部。它将节省您的时间和点击次数。如果你不测试它,就不要测试它……尽快到达你要去的地方。您不希望由于 UI 您没有尝试测试而导致测试失败,并且您始终希望测试尽可能快地进行。 (注意:您甚至可以直接导航到趋势 URL。)
您不需要 locateClickableElement()
函数。只需单击 links... 它应该是一个衬垫。如果有错误,那将是显而易见的。您不需要打印,"There was an error." 在打印异常消息后。
您不需要 stopTest()
功能...只需停止测试即可。当浏览器关闭时,会很明显测试完成。
重写后的代码如下。它很好,很简单(也很短),应该会更快。
public class youtubeTest
{
// do no change any of the below
private String testUrl = "https://www.youtube.com"; // target url destination ie youtube
private WebDriver driver; // webdriver instance to reference within class
private By trendingGuideLinkLocator = By.cssSelector("#trending-guide-item");
private By trendingLinkLocator = By.xpath("//h2[contains(.,'Trending')]");
@Before
public void beforeTest()
{
System.out.println("Setting up Test..."); // if you are going to have this statement, put it at the start of beforeTest()
driver = new SafariDriver();
driver.get(testUrl);
System.out.println("Set Driver " + driver + "for url: " + testUrl);
}
@Test
public void Test()
{
// insert unit tests within here
driver.findElement(trendingLinkLocator).click(); // just click the Trending link, it's faster
driver.findElements(trendingGuideLinkLocator).get(3).click();
}
@After
public void afterTest()
{
driver.close();
driver.quit();
}
}
如果您不想改变这一切,您问题的简单答案是将 FluentWait
替换为 WebDriverWait
。
fluentWait(By.cssSelector(ExpectedElement)).click();
将被替换为
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(trendingLinkLocator)).click();
所以我之前让它工作,但我在我的代码中搞砸了一些东西,现在 FluentWait 方法似乎没有正确调用。如果我 运行 它使用 quickRun
设置为 false 它按预期工作(因为隐式)但是当我将它设置为 true 它不会因为它不会等待元素正确加载。有谁知道我做错了什么吗?
package myPackage;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import com.google.common.base.Function;
//import com.gargoylesoftware.htmlunit.javascript.host.Console;
//https://www.codeproject.com/articles/143430/test-your-web-application-s-ui-with-junit-and-sele
//this will open a dynamic page example (ie. youtube) trending
public class youtubeTest {
public boolean quickRun = false; //Disable for debugging otherwise full speed
private static int defaultDebugDelay = 2; //Time in sec for next test to occur in debug
//do no change any of the below
private String testUrl; //target url destination ie youtube
private WebDriver driver; //webdriver instance to reference within class
private int testIndex = 1; //initial index value for console outputting
public WebElement fluentWait(final By locator) {
Wait < WebDriver > wait = new FluentWait < WebDriver > (driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function < WebDriver, WebElement > () {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
});
return foo;
};
@
Before
public void beforeTest() {
driver = new SafariDriver();
System.out.println("Setting up Test...");
if (quickRun) {
System.out.println("Test Type: Quick Run (Fastest Mode)");
} else {
System.out.println("Test Type: Slow Run (Debug Mode) - Each Test has a " + defaultDebugDelay + " sec call time buffer");
}
testUrl = "https://www.youtube.com";
driver.get(testUrl);
System.out.println("Setting Driver " + driver + "for url: " + testUrl);
}
@
Test
public void Test() {
//insert unit tests within here
//open yt nav menu
locateClickableElement("#appbar-guide-button");
//go to trending
locateClickableElement("#trending-guide-item");
//click on 4th Trending video from list
//locateClickableElement(".expanded-shelf-content-item-wrapper", 3);
locateClickableElement(".expanded-shelf-content-item-wrapper");
}
@
After
public void afterTest() throws Exception {
//wait 10 sec before closing test indefinitely
System.out.println("Test auto ending in 10 seconds...");
Thread.sleep(10000);
stopTest();
}
//individual unit tests
private void locateClickableElement(String ExpectedElement, int child) {
//format string into something like: "ELEMENT:nth-child(1)"
String formattedString = ExpectedElement + ":nth-child(" + child + ")";
System.out.println("Strung: " + formattedString);
locateClickableElement(formattedString);
}
private void locateClickableElement(String ExpectedElement) {
try {
System.out.println("Test " + testIndex + ": locateClickableElement(" + ExpectedElement + ")");
//do absolute delay for visual debugging
if (!quickRun) Thread.sleep(2000);
//click on target if found
fluentWait(By.cssSelector(ExpectedElement)).click();
System.out.println("Test " + testIndex + ": Successful Click on Element(" + ExpectedElement + ")");
} catch (Exception e) {
//whenever error is found output it and end program
System.out.println("Error Could not locateClickableElement(" + ExpectedElement + ")");
System.out.println("Exception Handled:" + e.getMessage());
stopTest("error");
}
testIndex++;
}
private void stopTest() {
System.out.println("Test Completed: Reached End.");
driver.quit();
}
private void stopTest(String typeError) {
System.out.println("Test Completed: With an Error.");
driver.quit();
}
}
我会以不同的方式写这篇文章并提供一些建议。
不要使用 "debug mode" 减慢测试速度。如果您想调试您的测试,请使用断点并单步执行代码以查看它是如何工作的。
这里不需要
FluentWait
。使用ExpectedConditions.elementToBeClickable(locator)
的简单WebDriverWait
就可以很好地工作并且不那么复杂。如果您接受我的更改,您甚至不需要它。不要使用
String
传递定位器,使用预期的定位器 class、By
。您无需对其进行解释、翻译等操作,而且速度更快、更灵活。除非您正在尝试测试 UI(我假设您不为 youtube 工作),否则您可以使用 Trending link 在页面顶部。它将节省您的时间和点击次数。如果你不测试它,就不要测试它……尽快到达你要去的地方。您不希望由于 UI 您没有尝试测试而导致测试失败,并且您始终希望测试尽可能快地进行。 (注意:您甚至可以直接导航到趋势 URL。)
您不需要
locateClickableElement()
函数。只需单击 links... 它应该是一个衬垫。如果有错误,那将是显而易见的。您不需要打印,"There was an error." 在打印异常消息后。您不需要
stopTest()
功能...只需停止测试即可。当浏览器关闭时,会很明显测试完成。
重写后的代码如下。它很好,很简单(也很短),应该会更快。
public class youtubeTest
{
// do no change any of the below
private String testUrl = "https://www.youtube.com"; // target url destination ie youtube
private WebDriver driver; // webdriver instance to reference within class
private By trendingGuideLinkLocator = By.cssSelector("#trending-guide-item");
private By trendingLinkLocator = By.xpath("//h2[contains(.,'Trending')]");
@Before
public void beforeTest()
{
System.out.println("Setting up Test..."); // if you are going to have this statement, put it at the start of beforeTest()
driver = new SafariDriver();
driver.get(testUrl);
System.out.println("Set Driver " + driver + "for url: " + testUrl);
}
@Test
public void Test()
{
// insert unit tests within here
driver.findElement(trendingLinkLocator).click(); // just click the Trending link, it's faster
driver.findElements(trendingGuideLinkLocator).get(3).click();
}
@After
public void afterTest()
{
driver.close();
driver.quit();
}
}
如果您不想改变这一切,您问题的简单答案是将 FluentWait
替换为 WebDriverWait
。
fluentWait(By.cssSelector(ExpectedElement)).click();
将被替换为
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(trendingLinkLocator)).click();