PHPUnit Selenium2 - No Browser Instance - phpunit

When I run even a sample test, either in Netbeans IDE of from the command line, e.g.:
class WebTest extends PHPUnit_Extensions_Selenium2TestCase
{
protected function setUp()
{
$this->setBrowser('firefox');
$this->setBrowserUrl('http://www.example.com/');
}
public function testTitle()
{
$this->url('http://www.example.com/');
$this->assertEquals('Example WWW Page', $this->title());
}
}
I get the PHPUnit response, but it doesn't seem to be communication with the Selenium server as no browser window was created.
PHPUnit 3.6.10 by Sebastian Bergmann.
Configuration read from /var/www/gcd/framework/yii/gadget/protected/tests/phpunit.xml
F
Time: 1 second, Memory: 10.50Mb
There was 1 failure:
1) WebTest::testTitle
Failed asserting that null matches expected 'Example WWW Page'.
Using PHPUnit 3.6.10 and selenium-server-standalone-2.21.0
Anyone any ideas?

Turns out, if you run PHPUnit with sudo, it works! Doh!

Related

phpunit test passes, page load in browser fails in Symfony 2

I am new to phpunit testing and did a very simple test looking for status code.
The test passes when I run:
bin\phpunit -c app src\AppBundle\Tests\Controller\StarLinX\TravelControllerTest.php
PHPUnit 4.6.10 by Sebastian Bergmann and contributors.
Configuration read from C:\PhpstormProjects\dir\app\phpunit.xml.dist
.
Time: 6.03 seconds, Memory: 20.00Mb
OK (1 test, 1 assertion)
But when I load the page in the browser, an exception is thrown rendering the twig file with status code 500.
I thought maybe this was a cache issue, so I cleared cache in --env=dev, prod and test.
How do I troubleshoot this error?
This is my test file:
namespace AppBundle\Tests\Controller\StarLinX;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class TravelControllerTest extends WebTestCase {
public function testGET() {
// Create a new client to browse the application
$client = static::createClient();
// get the page
$crawler = $client->request('GET', '/travel/aaaaa');
$this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /travel/aaaaa");
}
}
This is the error that is thrown when running in the dev environment:
An exception has been thrown during the rendering of a template ("Notice: Array to string conversion")
So after a little more analysis, I find that the error around {{ weatherInfo }} which should be {{ weatherInfo.now }}. This throws an error when running the development environment. In production, twig simply displays Array.
Is that normal behavior?
As it's written your test only check the error status, the test is not specific enough. What if it displayed another page? The test would still pass.
You should add some other tests in order to ensure that the page is properly displayed:
// …
$this->assertEquals(200, $client->getResponse()->getStatusCode(),
"Unexpected HTTP status code for GET /travel/aaaaa");
// Check that the page has a title.
$this->assertSame(
1,
$crawler->filter('title')->count()
);
// Check that the page has a correct title.
$this->assertSame(
'Travel',
$crawler->filter('title')->text()
);
// Check something in the content
$this->assertSame(
'Hello, World!',
$crawler->filter('body > div#content')->text()
);
If you don't have enough information to debug your code, tou can access to the page content which usually contain the error message:
die($this->client->getResponse()->getContent());

Service not found in container while setup for SECOND test (first is working)

I have wrote a testcase with a longer setUp which looks something like this:
public function setUp(){
$this->manager = $this->get('strego_tipp.invalidation_manager');
$mockEm = m::mock('Doctrine\Common\Persistence\ObjectManager');
$this->setAttribute($this->manager, 'em', $mockEm);
/* .... additional setup stuff ....*/
}
protected function get($service){
return $this->getContainer()->get($service);
}
This is just the setup, and now I have 2 tests in my testfile:
public function test_it_collects_not_duplicate_betRounds(){
$this->assertCount(0, $this->manager->betRounds);
$this->call($this->manager,'collectBetRoundWorkload', $this->game1);
$this->call($this->manager,'collectBetRoundWorkload', $this->game2);
$this->manager->collectBetRoundWorkload($this->game1);
$this->manager->collectBetRoundWorkload($this->game2);
$this->assertCount(2, $this->manager->betRounds);
}
public function test_it_collects_all_bets_to_update(){
$this->assertCount(0, $this->manager->bets);
$this->call($this->manager,'collectBetWorkload', $this->game1);
$this->manager->collectBetWorkload($this->game1);
$this->assertCount(3, $this->manager->bets);
}
When running the test, the second testcase always fails because within the setup there is no service named 'strego_tipp.invalidation_manager' in the container. Although the service was available in the first test. It is also independent from the actual testcase because I can change the order of the tests and still the service is not in the container for the second testcase. This seems to me like a very random problem and I can't get my head around it.
I solved that issue by cleaning cache because I was on prod environment:
$app/console cache:clear --env=prod
Hope it helps :)

How to stop assetic watch in Symfony2?

I followed the Symfony2 guide to automatically dump assetic files in dev mode:
I changed the use_controller parameter to false in my dev config file.
And I started the --watch routine.
$ php app/console assetic:dump --watch
How can I stop watching?
Command looking for file changes only while it working itself. So then you stop command - no more automatic regenerating assets.
On linux its typical ctrl+c or ctrl+x
P.S. some code from DumpCommand
while (true) {
try {
foreach ($this->am->getNames() as $name) {
if ($this->checkAsset($name, $previously)) {
$this->dumpAsset($name, $output);
}
}
// reset the asset manager
$prop->setValue($this->am, array());
$this->am->load();
file_put_contents($cache, serialize($previously));
$error = '';
} catch (\Exception $e) {
if ($error != $msg = $e->getMessage()) {
$output->writeln('<error>[error]</error> '.$msg);
$error = $msg;
}
}
sleep($input->getOption('period'));
}
Like #forgottenbas points out the code runs in an infinite loop so it's not really a background worker but simply a worker that occupies your shell until an outside force intervenes.
Generally the developer can kill the process or the shell session it's occupying.
On OSX ctrl + c sends SIGKILL, for instance.
In Windows it seems to work a bit differently in Window shells: http://en.wikipedia.org/wiki/Kill_(command)#Microsoft_Windows
It's definitely OS, or more accurately, shell dependent.
If you have spawned a linux background process, e.g.:
$ php app/console assetic:dump --watch &
you have to kill the php process that is running

Trouble running unit test - got undefined method error

I followed the instructions on this page but couldn't get my unit test working.
http://framework.zend.com/manual/2.2/en/tutorials/unittesting.html
My initial code was like this:
<?php
namespace ApplicationTest\Controller;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class IndexControllerTest extends AbstractHttpControllerTestCase {
protected $controller;
protected $request;
protected $response;
protected $routeMatch;
protected $event;
protected $traceError = true;
public function setUp() {
$this->setApplicationConfig(
include '../../../config/application.config.php'
);
parent::setUp();
}
public function testIndexActionCanBeAccessed() {
$this->dispatch('/');
$this->assertResponseStatusCode(200);
}
}
And when I ran phpunit, I got the following error message:
PHPUnit 3.7.21 by Sebastian Bergmann.
Configuration read from /usr/share/php/tool/module/Application/test/phpunit.xml
onDispatch called.
E
Time: 1 second, Memory: 14.50Mb
There was 1 error:
1) ApplicationTest\Controller\IndexControllerTest::testIndexActionCanBeAccessed
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
Then I followed the second set of instructions to configure the service manager.
public function testIndexActionCanBeAccessed() {
$albumTableMock = $this->getMockBuilder('User\Model\UserData')
->disableOriginalConstructor()
->getMock();
$albumTableMock->expects($this->once())
->method('getUserSessionArray')
->will($this->returnValue(array()));
$serviceManager = $this->getApplicationServiceLocator();
$serviceManager->setAllowOverride(true);
$serviceManager->setService('User\Model\UserData', $albumTableMock);
$this->dispatch('/');
$this->assertResponseStatusCode(200);
}
And this time, I got the following error:
PHPUnit 3.7.21 by Sebastian Bergmann.
Configuration read from /usr/share/php/tool/module/Application/test/phpunit.xml
onDispatch called.
PHP Fatal error: Call to undefined method Mock_UserData_ae821217::getUserSessionArray() in /usr/share/php/tool/module/User/Module.php on line 95
PHP Stack trace:
PHP 1. {main}() /usr/local/pear/bin/phpunit:0
…
Could someone help me on this please?
We are using Zend Framework 2.2.0.
Thank you so much.
EC
Your mock isn't quite setup right. You don't set any methods for the mock to have and so your expects isn't really being set. You need to create your mock like this:
$albumTableMock = $this->getMockBuilder('User\Model\UserData')
->disableOriginalConstructor()
->setMethods(array('getUserSessionArray')) //ADD this line
->getMock();
Your User\Model\UserData class doesn't exist and so PHPUnit did not create the method to get mocked. And when you ran your tests the function was not defined.

Using Selenium Grid 2 with PHPUnit tests

I have recently written a lot of selenium 1 tests for a fairly complex project. They are all written in php and run smoothly on the selenium-server 1.0.7.
Obviously with firefox 5 (and 6 released today) selenium server 1.0.7 is not working anymore. I've tried, but the server is just opening blank windows.
Now I am trying to get those tests running on selenium grid. I managed to get a hub and a couple of remote-controls runnnig using grid v1, but they only open blank windows just like the old server did. So I figured i needed to upgrade to grid v2.
For some reason i can get the clients connected to the hub, but if I try running my tests against the hub it doesn't seem to be able to connect at all ("PHPUnit_Framework_Exception: Could not connect to the Selenium RC server"). I tried running them against selenium standalone server 2.4.0 and that does seem to work.
I read in a forum, that selenium grid 2 just doesn't work with phpunit (yet?).
How can i get my tests running on a grid? What is missing for phpunit to connect to the server? I appreciate any help!
I set up the hub as follows:
java -jar selenium-server-standalone-2.4.0.jar -role hub
And two slaves:
java -jar selenium-server-standalone-2.4.0.jar -role rc -hub http://127.0.0.1:4444/grid/register -port 5555
java -jar selenium-server-standalone-2.4.0.jar -role webdriver -hub http://127.0.0.1:4444/grid/register -port 5556
Everything seems to be working till here as i see two nodes in the grid console (http://localhost:4444/grid/console).
So here is all the initialization I am doing in code:
<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
class Grid_Test extends PHPUnit_Extensions_SeleniumTestCase
{
public $captureScreenshotOnFailure = false;
public static $browsers = array(
'FFLinux' => array(
'name' => 'Firefox on Linux',
'browser' => '*firefox',
'host' => '127.0.0.1',
'port' => 4444,
'timeout' => 30000
));
public function setUp()
{
$this->setBrowserUrl('http://www.google.com');
}
public function testGridWorking()
{
$this->open('/');
$this->assertTrue(false);
}
}
This code still works on the standalone server 2.4.0. It fails at the last line as expected.
The Exception seems to be thrown in PHPUnit/Extentions/SeleniumTestCase/Driver.php. There seems to be the problem.
protected function doCommand($command, array $arguments = array())
{
$url = sprintf(
'http://%s:%s/selenium-server/driver/?cmd=%s',
$this->host,
$this->port,
urlencode($command)
);
[...]
$handle = #fopen($url, 'r', FALSE, $context);
if (!$handle) {
throw new PHPUnit_Framework_Exception(
'Could not connect to the Selenium RC server.'
);
}
[...]
}
When i request http://localhost:4444/selenium-driver/driver in the browser, i get:
HTTP ERROR: 500
org.openqa.grid.internal.GridException: Session not available - []
RequestURI=/selenium-server/driver
Any idea how to fix this? Do I need to change that url maybe ?
Also make sure you have setup the Grid correctly here is a small post that shows how it is done : http://opensourcetester.co.uk/2011/07/06/selenium-grid-2/
BTW I dint see code that does the driver instantiation.. Am i missing something?
Here is how it is done:
require_once "phpwebdriver/WebDriver.php";
require("phpwebdriver/LocatorStrategy.php");
$webdriver = new WebDriver("localhost", "4444");
$webdriver->connect("firefox");
$webdriver->get("http://google.com");
$element = $webdriver->findElementBy(LocatorStrategy::name, "q");
$element->sendKeys(array("selenium google code" ) );
$element->submit();
$webdriver->close();
for more: http://code.google.com/p/php-webdriver-bindings/
The problem with trying to use PHPUnit with Selenium Grid 2 has already been reported to the project owners. Have a look at the patch available here to see if it works for you.
Anyway, if I were you I would start thinking about migrating to WebDriver through one of the drivers available out there for PHP, like php-webdriver.

Resources