2016-12-11 82 views
0

因此,我让它工作得更早,但是我弄乱了我的代码中的某些内容,现在FluentWait方法似乎没有正确调用。如果我运行它使用quickRun设置为false,它会按预期工作(因为隐式),但是当我将它设置为true时,它不会等待元素正确加载。有谁知道我做错了什么?FluentWait无法正常工作:Youtube示例

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(); 
 
    } 
 

 
}

回答

0

我会写这样一个不同的方式,并提供一些建议。

  1. 不要使用“调试模式”降低测试速度。如果您想调试您的测试,请使用断点并单步执行代码以查看它的工作方式。

  2. 这里你不需要FluentWait。一个简单的WebDriverWait使用ExpectedConditions.elementToBeClickable(locator)将工作得很好,并不复杂。如果您接受我的更改,您甚至不需要它。

  3. 请勿使用String传递定位器,请使用预期的定位器类By。你不需要翻译它,翻译它等,它会更快,更灵活。

  4. 除非您尝试测试用户界面(我假设您不适用于YouTube),那么您可以使用页面顶部的趋势链接导航到趋势页面。这将节省您的时间和点击。如果你不测试它,不要测试它......尽可能快地到达你要去的地方。你不希望你的测试失败,因为你没有尝试测试UI,你总是希望你的测试尽可能快。 (注意:您甚至可以直接导航到趋势URL。)

  5. 您不需要locateClickableElement()函数。只需点击链接...它应该是一个班轮。如果出现错误,这将是显而易见的。您不需要打印,“出现错误。”在打印异常消息之后。

  6. 你不需要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(); 
    } 
} 

如果你不想改变这一切,简单的回答你的问题是WebDriverWait取代FluentWait

fluentWait(By.cssSelector(ExpectedElement)).click(); 

将由

new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(trendingLinkLocator)).click(); 
+0

哇更换这真的帮助我了解了这么多。我应该记住保持简单。 1)好主意..我正在推翻它,生病一定要这样做。 2)我什么时候需要使用fluentwait?当加载时间非常难以预测? 3)请确保直接执行此操作,并按照您的示例进行声明4)我正在测试用于我们软件的UI。它主要是UI导航。它是一个定制的RocketChat应用程序。所以每个类是每个模块的单元测试?我会导航到链接还是我会参考一个公共静态驱动程序?我将这一切应用到我今天工作的代码中 – Potion

+0

'FluentWait'适用于需要自定义等待的情况......未由ExpectedConditions覆盖的情况。我建议你阅读一些Java单元测试最佳实践文章。我不做很多单元测试。 – JeffC

+0

我一定会进入更多的文章。由于这项任务几乎没有关于测试过程或方案的知识,因此我感到有些匆忙。感谢您的帮助 – Potion

相关问题