Reputation: 5268
When a test tries to open a page that doesn't load, and the timeout value is reached, the test doesn't stop or throw an exception. Instead it just moves on and acts as if the page is loaded successfully. It does its clicks and stops at the first assertion that returns false.
I found this in the commit log of PHPUnit 3.6.10: https://github.com/sebastianbergmann/phpunit/commit/cb772b06e9bd97f478fff7a212e3a4f7fe96bc29
In the source: https://github.com/sebastianbergmann/phpunit/blob/5d0ff52bdff9afd479e38fdc880adce453ce88e5/PHPUnit/Framework/TestResult.php#L665
The exception looks like it should still be caught, but unfortunately the exception doesn't seem to trigger the test to stop, so I am at a loss of what to do here.
Here is an example test to provoke the behaviour I am talking about:
<?php
class Example extends PHPUnit_Extensions_SeleniumTestCase
{
protected function setUp() {
$this->setBrowser('*firefox');
$this->setBrowserUrl('http://myserver/timeout.php');
$this->setTimeout(10);
$this->setWaitForPageToLoad(true);
}
public function testMyTestCase() {
// This should trigger an exception after timeout:
$this->openAndWait('/');
// Anything below this line SHOULD never be executed because of timeout:
$this->click('id=clicketyclickthiswontbeclicked');
$this->click('id=moreclicksthatwillnotbeclicked');
// This will fail the test, because timeout didn't stop it
$this->assertTextPresent('this text');
}
}
?>
The following PHP file should trigger a timeout.
timeout.php:
<?php
// Should trigger timeout
sleep(30);
// (...) Rest of the page
?>
Am I doing something wrong or could this be a bug?
Upvotes: 3
Views: 1128
Reputation: 5268
I'm going to answer myself here in case anyone else has this problem. As a workaround, I override the waitForPageToLoad
function. It calls the parent function and keeps track of the time it spends waiting for the page to load to determine if the page load actually timed out, and throws an exception if it did.
Here's the code for it:
protected function waitForPageToLoad( $timeout=null ) {
if ( is_null( $timeout ) ) {
$timeout = 30000;
}
$start = time();
parent::waitForPageToLoad( $timeout );
$end = time();
if ( ($end - $start) >= ($timeout / 1000) ) {
throw new Exception( 'Timed out after '.$timeout.'ms.' );
}
}
This seems incredibly unnecessary, but at the moment, it works for me, but I would still like an answer that doesn't require such a hack.
Upvotes: 1