【问题标题】:php-webdriver: wait for browser response after submitting form using click()php-webdriver:使用 click() 提交表单后等待浏览器响应
【发布时间】:2013-01-06 04:21:12
【问题描述】:

除了在我的测试中使用sleep() 之外,我想知道是否有人知道在继续我的断言之前明确等待表单提交 (POST) 完成的更好策略。这是我的测试的一个非常精简的版本,使用 phpunit 一起使用 php-webdriver 来自 Facebook)。

function test_form_submission()
{   
    // setup
    $web_driver = new WebDriver();
    $session = $web_driver->session();
    $session->open('http://example.com/login');

    // enter data
    $session->element('css selector', 'input[name=email]')->value(array('value' => str_split('test@example.com')));
    $session->element('css selector', 'input[name=password]')->value(array('value' => str_split('testpassword')));

    // click button to submit form
    $session->element('css selector', 'button[name=submit]')->click();

    // How do I wait here until the click() above submits the form
    // so I can check that we correctly arrives at the destination below
    // without resorting to sleep()?

    // Confirm that login was successful because we landed on account page
    $this->assertSame('http://example.com/account', $session->url());

    // teardown
    $session->close();
}

【问题讨论】:

  • 那么,当您现在执行此代码时,倒数第二行(断言)中的 url 给出的是 example.com/login 而不是 example.com/account?据推测,Selenium 服务器应该等到页面加载完毕后再查找元素。异步请求是个例外,但您的请求看起来非常同步。请注意,我正在使用 PHPUnit_Selenium 来驱动 Selenium
  • 没错。事实上,我当时也可以截屏,看到我仍在 example.com/login 上,但如果我睡 1 秒,断言通过,截屏显示页面现在是示例。 com/帐户。我读到 PHPUnit_Selenium 还不能运行 Selenium 2(又名 webdriver),所以这就是我采用上述方法的原因。

标签: php selenium phpunit selenium-webdriver


【解决方案1】:

来自 Facebook 的php-webdriver 已于 2013 年 6 月重写。您可以像这样轻松等待 URL。

// wait for at most 10 seconds until the URL is 'http://example.com/account'.
// check again 500ms after the previous attempt.
$driver->wait(10, 500)->until(function ($driver) {
  return $driver->getCurrentURL() === 'http://example.com/account';
})

【讨论】:

  • 如果url是动态创建的呢?例如:site.com/item?id=123&color=black&size=small
  • 通过正则表达式匹配网址。
【解决方案2】:

好的,所以我知道这是一个非常古老的问题,但是当我通过 Google 偶然发现它时,我希望这对某人仍然有用(甚至可能是 OP?:-))。

在谷歌代码上搜索和阅读文章和消息后,我找到了一个我认为非常丑陋的解决方案,但实际上并没有一个好的选择。您可以阅读here,WebDriver 无法检测到页面何时加载。所以,我们必须恢复等待。现在,OP 正在使用 Facebook 的 PHP WebDriver,它不包括等待实用程序 AFAIK,但是当使用 this maintained clone 时,您将获得 WebDriverWait 的实现。

现在的问题是:我们还在等什么?您可以等待 URL 更改,但这绝不是一种可靠的方法,因为当 URL 已经更改时,页面可能尚未加载。下一个选项:等待您知道要加载的页面上的元素出现。这行得通,但是如果您想要更通用的方法怎么办?幸运的是,我读到了上面提到的一个非常好的想法in the thread。您可以等待两个页面上的元素消失并重新出现,例如页脚。

我刚刚实现了这个,它似乎工作。下面的函数可以传递你的$session,并且只会在新页面加载时返回(或者至少页脚再次可用)。

public static function waitForNextPage($pWDSession) {
    $aWait = new PHPWebDriver_WebDriverWait($pWDSession);
    // wait for footer to not be available anymore
    $aWait->until(
            function($pWDSession) {
                return (0 === count($pWDSession->elements(PHPWebDriver_WebDriverBy::CSS_SELECTOR, "#footer,#mx-footer")));
            }
        );
    // wait for footer to be available again
    $aWait->until(
            function($pWDSession) {
                return (0 < count($pWDSession->elements(PHPWebDriver_WebDriverBy::CSS_SELECTOR, "#footer,#mx-footer")));
            }
        );
}

您显然可以更改选择器或使用其他元素,想法保持不变。

希望对你有帮助!干杯!

【讨论】:

    【解决方案3】:

    应该可以使用clickAndWait() 代替click(),以便等到下一页加载完毕。

    【讨论】:

    • 我不确定它是否适用于 php-webdriver。我收到以下错误:“异常:clickAndWait 不是有效的 webdriver 命令。”
    【解决方案4】:

    您可以使用Implicit Wait and Explicit Wait 等待特定的Web 元素,直到它出现在页面中。您可以定义的等待时间取决于应用程序。

    显式等待:

    显式等待是您定义的代码,用于等待特定条件发生,然后再继续执行代码。如果条件达到,它将终止等待并继续执行进一步的步骤。

    代码:

     WebDriverWait wait = new WebDriverWait(driver,30);
     wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(strEdit)));
    

    或者

     WebElement myDynamicElement = (new WebDriverWait(driver, 30))
     .until(new ExpectedCondition<WebElement>(){
    @Override
    public WebElement apply(WebDriver d) {
        return d.findElement(By.id("myDynamicElement"));
    }});
    

    这会在抛出 TimeoutException 之前等待最多 30 秒,或者如果它发现元素将在 0 - 30 秒内返回它。默认情况下,WebDriverWait 每 500 毫秒调用一次 ExpectedCondition,直到它成功返回。对于 ExpectedCondition 类型的成功返回是 Boolean 对所有其他 ExpectedCondition 类型返回 true 或非 null 返回值。

    您可以根据应用程序的需要使用 ExpectedConditions 类。

    隐式等待:

    隐式等待是告诉 WebDriver 在尝试查找一个或多个元素(如果它们不是立即可用)时轮询 DOM 一段时间

    代码:

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

    要记住的一点是,一旦设置了隐式等待 - 它将在 WebDriver 对象实例的生命周期内一直存在

    欲了解更多信息,请使用此链接http://seleniumhq.org/docs/04_webdriver_advanced.jsp

    【讨论】:

    • 我特意要求一个使用 php-webdriver 的 PHP 解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 2017-10-09
    • 2022-12-11
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    相关资源
    最近更新 更多