如何设置Selenium WebDriver的获取超时时间?

46

在使用像FirefoxDriver这样的WebDriver代理时,如果代理不好,那么get方法将会永远阻塞。我设置了一些超时参数,但无效。

这是我的代码:

FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("general.useragent.override", ua);    
Proxy p = new Proxy();
p.setHttpProxy(proxy);
profile.setProxyPreferences(p);
profile.setEnableNativeEvents(true);

// create a driver
WebDriver driver = new FirefoxDriver(profile);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
driver.get("www.sina.com.cn")

调用driver.get将永远阻塞,但我希望它等待30秒钟,如果页面没有加载完成,则抛出异常。

8个回答

42

试试这个:

 driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

4
就我所写的内容而言,此答案已被接受为正确答案。然而,正如zhongting在下面提到的那样,这个解决方案似乎会阻塞加载很长时间。我认为实际的答案应该是user1102631的 - Steve HHH
2
同意,这个答案将给每个Selenium运行的命令添加30秒的延迟。这样任意的延迟是非常昂贵且通常不可靠的方式来使测试工作。通常最好将隐式等待设置为0,并针对每个操作使用显式等待结果。这样更可靠,通常更快,因为您只需等待动作发生而不是每次都等待完整的时间限制。 - ajsutton
@ajsutton 你如何显式地等待? - Thufir
5
@ajsutton,它是如何在每个命令中添加30秒延迟的呢?implicitwait会轮询DOM,直到元素可用的给定时间为止。如果在30秒之前就可以使用这些元素,它将中断等待并继续执行。 - Vivek Singh
如何在JS中实现,JS无法做到这一点。 - Zeeshan Ahmad Khalil
显示剩余2条评论

30

timeouts() 方法在某些驱动程序中没有实现,并且通常非常不可靠。
我使用一个单独的线程来处理超时(将要访问的URL作为线程名称传递):

Thread t = new Thread(new Runnable() {
    public void run() {
        driver.get(Thread.currentThread().getName());
    }
}, url);
t.start();
try {
    t.join(YOUR_TIMEOUT_HERE_IN_MS);
} catch (InterruptedException e) { // ignore
}
if (t.isAlive()) { // Thread still alive, we need to abort
    logger.warning("Timeout on loading page " + url);
    t.interrupt();
}

这似乎大多数时候都有效,但可能会发生驱动程序真的卡住了,任何后续对驱动程序的调用都将被阻塞(我在Windows上使用Chrome驱动程序时遇到过这种情况)。即使是像driver.findElements()这样无害的调用也可能被阻塞。不幸的是,我没有解决被阻塞驱动程序的方法。


1
如果您将Selenium与用户脚本(通过扩展和保存配置文件)混合使用,即使Selenium被阻止等待加载,您仍然可以将JavaScript代码发送到浏览器中。这样,您可以添加一个简单的JavaScript setTimeout(function(){window.stop();}, 5000),其中包含所需的时间(以毫秒为单位),然后停止页面加载。一旦您停止加载,控制权就会被发送回Selenium(只需运行测试,然后在加载时按ESC键)。这种方式允许您加载仅5秒的网页并获取常见的Web元素。 - m3nda

18

尝试

driver.executeScript("window.location.href='http://www.sina.com.cn'")

如果您将pageLoadStrategy设置为none,则此语句将立即返回。

之后,您可以添加一个具有超时的WebDriverWait来检查页面标题或任何元素是否正常。

希望这能帮到您。


3
这是我使用ChromeDriver的最简易工作解决方案,因为它不支持页面加载超时设置。在Python中也可行(使用execute_script函数)。 - chris838
2
不错!解决了我在 Python 中对抗 socket.timeout 异常的好方法。我更喜欢处理 selenium 的 TimeoutException。 - Donn Lee
1
是的!这也是我在寻找的。我使用了get()WebDriverWait,并在try catch中设置了3秒的超时时间。但是由于等待发生在get而不是WebDriverWait中,所以有时这个块需要300秒才能终止。使用execute_script(我在Python中)代替get()解决了这个问题。 - Hashimoto
@JasonYou 我已经编辑了你的答案,插入了文本“If you have set pageLoadStrategy to none,”。根据我的测试,如果是“eager”,我需要等待几秒钟才能到达下一行代码。 - P i

8
我有同样的问题,感谢这个论坛和其他一些资源,我找到了答案。 最初我也考虑使用单独的线程,但它会使代码变得更加复杂。因此,我尝试寻找符合我的原则“优雅和简单”的答案。
请查看这样的论坛: https://sqa.stackexchange.com/questions/2606/what-is-seleniums-default-timeout-for-page-loading 解决方案: 在代码中,在具有“get”方法的行之前,例如:
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);

其中一个问题是它会抛出timeoutException异常,所以你需要将其封装在try catch块中或包装在某个方法中。

我还没有找到pageLoadTimeout的getter方法,所以我不知道默认值是多少,但很可能非常高,因为我的脚本被冻结了好几个小时,没有任何进展。

注意: Chrome驱动程序未实现“pageLoadTimeout”,因此会引发异常。根据用户评论,我看到有计划对其进行改进。


OP尝试了pageLoadTimeout,但对他/她的情况没有起作用。 - Packard CPW
我实际上在最新的ChromeDriver版本101.0.4951.41中使用了这个超时功能,它也起作用了。我将其设置为5秒,虽然看起来超时时间似乎比5秒长,但驱动程序报告已经过去了大约4.98秒。我也不想使用线程,所以这对我的目的来说是一个不错的简单解决方案。 - Dave

2
您可以像这样在HTTP客户端上设置超时时间。
int connectionTimeout=5000;
int socketTimeout=15000;
ApacheHttpClient.Factory clientFactory = new ApacheHttpClient.Factory(new HttpClientFactory(connectionTimeout, socketTimeout));
HttpCommandExecutor executor =
      new HttpCommandExecutor(new HashMap<String, CommandInfo>(), new URL(seleniumServerUrl), clientFactory);
RemoteWebDriver driver = new RemoteWebDriver(executor, capabilities);

这个解决方案已经不再适用了,有人能提供最新的解决方案吗? - Omkar Nath Singh

1
< p > driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS) 的解决方案将适用于同步加载的页面。然而,这并不能解决异步加载页面的问题,如果我们设置了pageLoadTimeOut,那么测试将一直失败。


0

我发现在实际应用中,超时调用并不是非常可靠,特别是对于Internet Explorer。但以下解决方案可能会有所帮助:

  1. 您可以在运行Selenium进程的JUnit测试中使用@Test(timeout=10000)来超时完成整个测试。这将释放主线程以执行其他测试,而不是阻塞整个过程。但是,即使如此,有时也无法正常工作。

  2. 无论如何,通过超时,您并不打算挽救测试用例,因为即使超时单个操作,也可能导致整个测试序列处于不一致状态。您可能只想继续进行其他测试用例而不阻塞(或者重试相同的测试)。在这种情况下,一个万无一失的方法是编写一个轮询器,轮询Webdriver进程(例如IEDriverServer.exe、Phantomjs.exe)是否运行超过10分钟,并杀死它们。一个示例可以在自动识别(和杀死)长时间处理的进程中找到。


-1

在类似的情况下使用以下代码

driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);

在try-catch语句中嵌入driver.get代码,解决了加载超过1分钟的页面的问题。

2
给你的答案添加一些解释 - mumair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接