How to enable Doctrine query logging in Symfony 1.4 unit tests - unit-testing

I am unit testing a model class and I would like all Doctrine queries to be logged.
My settings.yml for the test environment contains
logging_enabled: true
and my script
$configuration = ProjectConfiguration::getApplicationConfiguration( 'frontend', 'test', true);
new sfDatabaseManager( $configuration ) ;
Still, I don't see any log in any log file.

So, I found a workaround by using an event listener on the Doctrine profiler.
$profiler = new Doctrine_Connection_Profiler();
$conn = Doctrine_Manager::connection();
$conn->setListener($profiler);
/* tests go here */
foreach ($profiler as $event) {
echo $event->getQuery() . "\n";
}
But the same query is printed out several times for some reason (I am sure it is executed only once). Plus it is not so convenient to have the query logs dissociated from the rest of the log messages.

Related

Include all App loads in UnitTests

I'm attemption a UnitTest like this in FuelPHP:
/**
* Products class tests
*
* #group App
* #group Products
*/
class Test_Model_Products extends Fuel\Core\TestCase
{
public function test_foo() {
$m = new Model_Productpropertytype;
$m->name = 'Text';
$m->save();
}
}
..but there seems to be namespace issues. How can I get the TestCase to not fail on the loaded ORM?
1) Test_Model_Products::test_foo
Fuel\Core\Database_Exception: SQLSTATE[HY000] [2002] No such file or directory
This does not look like an auto loading problem, the error, to me, says that there is a problem with you SQL connection. Fuel uses a separate DB config for the development, testing and production environments.
If you set up a db.php config file in fuel/app/config/testing/db.php it will be used to make any DB connections when running unit tests via oil

PHPUnit with Selenium2 - share session not working

I'm doing some tests with PHPUnit and Selenium and i would like all of them to run in the same browser window.
I've tried starting the Selenium Server with
java -jar c:\php\selenium-server-standalone-2.33.0.jar -browserSessionReuse
but with no visible change.
I've also tried with shareSession() in the setup
public function setUp()
{
$this->setHost('localhost');
$this->setPort(4444);
$this->setBrowser('firefox');
$this->shareSession(true);
$this->setBrowserUrl('http://localhost/project');
}
but the only change is that it opens a window for every test, and not really sharing the session. I'm out of ideas at this point.
My tests look like this:
public function testHasLoginForm()
{
$this->url('');
$email = $this->byName('email');
$password = $this->byName('password');
$this->assertEquals('', $email->value());
$this->assertEquals('', $password->value());
}
Here's the elegant solution. To share browser sessions in Selenium2TestCase, you must set sessionStrategy => 'shared' in your initial browser setup:
public static $browsers = array(
array(
'...
'browserName' => 'iexplorer',
'sessionStrategy' => 'shared',
...
)
);
The alternative (default) is 'isolated'.
You do not need to use the flag -browserSessionReuse
In your case The set up function running before every test and starting new instance.
This is what i did to prevent this to happen (Its little bit ugly but work for me both in Windows and Ubuntu):
I created helper class with static ver: $first and initialized it.
helper.php:
<?php
class helper
{
public static $first;
}
helper::$first = 0;
?>
Edit main test file setUp() function(and add require_once to helper.php):
require_once "helper.php";
class mySeleniumTest extends PHPUnit_Extensions_SeleniumTestCase
{
public function setUp()
{
$this->setHost('localhost');
$this->setPort(4444);
if (helper::$first == 0 )
{
$this->shareSession(TRUE);
$this->setBrowser('firefox');
$this->setBrowserUrl('http://localhost/project');
helper::$first = 1 ;
}
}
....
setHost and setPort outside the if because the values restarted after each test(For me...) and need to set up every time (if the selenium server is not localhost:4444)
Just found an (much) faster way to proceed : If you perform several test in one function, all test are performed in the same window. The setback is that the tests and reporting won't be nicely presented by tests, but the speed is way up!
In the same function for each test just use:
$this->url('...');
Or
$this->back();

Zend Framework - Doctrine2 - Repository Query Caching

I'm looking at Caching and how to use it in Doctrine.
I've got the following in my Zend Framework Bootstrap.php:
// Build Configuration
$orm_config = new \Doctrine\ORM\Configuration();
// Caching
$cacheOptions = $options['cache']['backendOptions'];
$cache = new \Doctrine\Common\Cache\MemcacheCache();
$memcache = new Memcache;
$memcache->connect($cacheOptions['servers']['host'], $cacheOptions['servers']['port']);
$cache->setMemcache($memcache);
$orm_config->setMetadataCacheImpl($cache);
$orm_config->setQueryCacheImpl($cache);
$orm_config->setResultCacheImpl($cache);
I'm running a very simple query on my DB using:
self::_instance()->_em->getRepository('UserManagement\Users')->find('1');
And I'm not sure if I'm using caching properly, because with it on (as
per the above config) the query seems to take twice as long to execute
as with it disabled, is this right?
Thanks in advance,
Steve
I seem to have sorted this myself, sort of related to enter link description here. Basically, from what I understand a repository query like:
self::_instance()->_em->getRepository('UserManagement\Users')->find('1');
Will not cache the results. If the same query is executed again throughout the script processing, it will not perform the search and use the result it has in memory - this isn't the same as real caching, in my case using Memcache.
The only way to achieve this, is to override the Doctrine EntityRepository find() method in a custom repository with something like:
public function find($id)
{
// Retrieve an instance of the Entity Manager
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('u')
->from('UserManagement\Users', 'u')
->where('u.id = :id')
->setParameter('id', $id);
$query = $qb->getQuery();
$query->useResultCache(TRUE);
$result = $query->getSingleResult();
return $result;
}
Notably, the most important line from the above is $query->useResultCache(TRUE); - this informs the Application to cache the results.
Hope this helps.

Updating schema for one entity without deleting everything else

When I run a schema update it successfully updates the schemas for my entities, but if there are any 'non-doctrine' tables in the database it deletes them. Unfortunately, these other tables are required for the 3rd party CMS I'm using.
Is there a way to tell doctrine to update the schema for certain entities (or all of them) without deleting anything else?
Below is my existing update code. The $classes array contains all the meta data for entity classes found in several different plugins.
//$em is an instance of EntityManager
//Psuedo Code
$classes = array(
$em->getClassMetadata('class1'),
$em->getClassMetadata('class2'),
$em->getClassMetadata('class3'),
$em->getClassMetadata('class4'),
$em->getClassMetadata('class5'),
);
//Real Code
$st = new Doctrine\ORM\Tools\SchemaTool( $em );
if ($classes)
$st->updateSchema($classes);
This gets all of the update sql but parses out any drop statements:
$sql = $st->getUpdateSchemaSql( $classes );
$count = count($sql);
for($i=0; $i<$count; $i++)
{
if(substr($sql[$i], 0, 4) == 'DROP')
unset($sql[$i]);
}
foreach($sql as $statement)
{
$em->getConnection()->exec( $statement );
}
You could run the schema tool with --dump-sql instead of --force, copy and paste the output from --dump-sql and run it on your database manually (of course removing the DROP statements for the tables you want to preserve.)

ZF, ZFDoctrine and PHPUnit setup

Does anyone here use Zend Framework, ZFDoctrine and PHPUnit together?
How to rebuild the database on each test run?
How to separate local/production/testing environments?
Would you share your unit testing setup?
I have been trying something like that:
// /tests/bootstrap.php
// ... setup paths and constants here
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap('doctrine');
$provider = new ZFDoctrine_Tool_DoctrineProvider;
$provider->generateModelsFromYaml();
//$provider->buildProject(true);
But this ends in:
Notice: Constant APPLICATION_PATH already defined in /home/user/www/library/ZendFramework/1.10.7/library/Zend/Tool/Project/Context/Zf/BootstrapFile.php on line 106
Fatal error: Call to a member function getResponse() on a non-object in /home/user/www/library/zf-doctrine/library/ZFDoctrine/Tool/DoctrineProvider.php on line 271
Models are not generated.
I get similar errors running:
$provider->createDatabase();
But in this case database is created.
The other provider commands do not work.
The solution:
$provider = new ZFDoctrine_Tool_DoctrineProvider;
$registry = new Zend_Tool_Framework_Registry;
$provider->setRegistry($registry);
#$provider->buildProject(true);
If anybody knows a better approach, please correct me.
I haven't used ZFDoctrine, but just plain Doctrine 1.2. I don't know if my solution is better but I figured I post if any1 is interested, here's the bootstrap.php in my tests folder:
<?php
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../application'));
// Define application environment
/**
* In the application.ini:
[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
doctrine.dsn = "mysql://my_user:passwd#localhost/my_phpunit_test_db"
*/
define('APPLICATION_ENV', 'testing');
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
get_include_path()
)));
/** Zend_Application */
require_once 'Zend/Application.php';
// Create application, bootstrap, and run
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/../configs/application.ini'
);
$application->getBootstrap()->bootstrap();
// Can run out if too small
ini_set('memory_limit', '512M');
// Get the doctrine settings
$config = $application->getOption('doctrine');
$cli = new Doctrine_Cli($config);
$cli->run(array("doctrine", "build-all-reload","force"));
The key here is actually the last line that rebuilds all databases creating a clean environment for each testing.