-
Notifications
You must be signed in to change notification settings - Fork 0
OSS PHP Frameworks Unit Testing: CakePHP
CakePHP is a very popular rapid development framework for PHP, highlighting design patterns such as MVC.
Note: This is a framework that does not directly use PHPUnit to run its unit tests. While PHPUnit is the underlying framework, the tests are run via a wrapper around PHPUnit.
Download the latest master branch from Github
The documentation to run the unit tests are found here: http://book.cakephp.org/2.0/en/development/testing.html
We followed the instructions for running the tests at the command line (see the "Running tests from command line" in the link above). Below are some additional steps we took to get the tests running correctly.
In order to run the CakePHP unit tests successfully, make sure you have HHVM, Composer and other basic packages ready to go.
Some initial configuration is required for CakePHP, particularly around a sample database and dependencies.
A sample database is necessary to run the unit tests. We used MySQL to setup the sample database. There are many links online to help install MySQL on CentOS 6. Here is one: http://centoshelp.org/servers/database/installing-configuring-mysql-server/
Copy app/Config/database.php.default
to app/Config/database.php
and change the $test
variable to look something like this (particular to your sample database setup):
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => '127.0.0.1',
'login' => 'cakeuser',
'password' => 'mypass',
'database' => 'test_cakephp',
'prefix' => '',
//'encoding' => 'utf8',
);
The CakePHP source comes with an empty vendors
directory, implying that some dependencies may be needed to run the unit tests. Indeed, since CakePHP has an underlying dependency on PHPUnit, PHPUnit dependencies are needed. So, we created a composer.json
file in the root CakePHP directory that looked like this:
{
"config": {
"vendor-dir": "vendors"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
}
}
Then we used composer to install the dependencies.
We are hoping this is a mistake on our end, but we had to make some code changes in order to get the tests to run correctly:
In lib/Cake/Console/cake
, change the exec
line to look like:
exec hhvm "$CONSOLE"/cake.php -working "$APP" "$@"
We removed -q
as well from the line above.
In lib/Cake/TestSuite/CakeTestSuiteDispatcher.php
, we had to change
if (is_dir($vendor . DS . 'PHPUnit')) {
to
if (is_dir($vendor . DS . 'phpunit' . DS . 'phpunit' . DS . 'PHPUnit')) {
AND
include 'PHPUnit' . DS . 'Autoload.php';
to
include 'phpunit'. DS . 'phpunit'. DS . 'PHPUnit' . DS . 'Autoload.php';
To run the CakePHP unit tests, use the following command from the root CakePHP directory (sudo
may be necessary):
[sudo] lib/Cake/Console/cake test core AllTests
The first fatal we were greeted to was:
HipHop Fatal error: Cannot use 'String' as class name as it is reserved in /data/users/joelm/php-open-source-projects/cakephp/lib/Cake/Utility/String.php on line 27
This fatal turns out to be a near showstopper for us. HHVM does not allow primitives to be used as class names. After trying unsuccessfully to turn HipHop syntax off via EnableHipHopSyntax=false
, we went the brute force route of trying to rename String
to CakeString
throughout the code. This is obviously not optimal, but it got the tests moving again.
Important Note: If you go down the route of renaming the class, and use an automated system, make sure you do this from inside the lib
directory to avoid changing non-git tracked files in directories like vendor
.
The script we ran to make the class change looked like this:
cd /home/joelm/local/php-open-source-projects/cakephp/lib && find . -name "*.php
" -print | xargs sed -i 's/class String/class CakeString/g' && find . -name "*.p
hp" -print | xargs sed -i 's/String::/CakeString::/g' && find . -name "*.php" -p
rint | xargs sed -i 's/String()/CakeString()/g' && find . -name "*.php" -print |
xargs sed -i 's/App::uses(\x27String\x27/App::uses(\x27CakeString\x27/g'
We found out that we did not implement RegexIterator.
HipHop Fatal error: Class undefined: RegexIterator in /data/users/joelm/php-open-source-projects/cakephp/lib/Cake/Core/App.php on line 471
Our autoloading needs some love. We were getting stackoverflow fatals.
HipHop Fatal error: Stack overflow in /data/users/joelm/php-open-source-projects/cakephp/vendors/composer/ClassLoader.php on line 184
Here are some good issue threads that deals with this issue:
https://github.com/facebook/hiphop-php/issues/1036
https://github.com/facebook/hiphop-php/pull/959
After getting through the fatals, there were errors and failures in functionality.
Our implementation of preg_replace_callback() does not work well with strings that contains tags.
HipHop Notice: Undefined index: info in /data/users/joelm/php-open-source-projects/cakephp/lib/Cake/Console/ConsoleOutput.php on line 220
Here is some test code that reproduces this issue:
<?php
class MyTest {
protected static $_styles = array(
'error' => array('text' => 'red', 'underline' => true),
'warning' => array('text' => 'yellow'),
);
public function styleText($text) {
return preg_replace_callback(
'/<(?P<tag>[a-z0-9-_]+)>(?P<text>.*?)<\/(\1)>/ims', array($this, '_replaceTags'), $text
);
}
protected function _replaceTags($matches) {
$x = $matches['tag'];
return $matches['text'];
}
}
$m = new MyTest();
//$m->styleText("Welcome to CakePHP v2.4.0 Console"); WORKS!
$m->styleText("<info>Welcome to CakePHP v2.4.0 Console</info>"); // DOESN'T WORK!
There are obviously some fixes that need to be made on the HHVM side in order to get the CakePHP unit tests to run correctly. However, it would be great to discuss with CakePHP core developers about possibly changing the String
class to another name.