Unit testing Zend Framework 1.x with PHPStorm

Warning: This post is outdated. If you want something more up-to-date: The Dutch Web Alliance has an excellent series on unit testing and debugging with PHPStorm, by Joshua Thijssen

In case I ever forget, to easisly install the latest phpunit, follow the manual blindly, which means to:

go-pear
pear update pear

At the moment of writing, the above yields an error, complaining about Strutures\Graph.php. The solution is to get the Structures_Graph tar by typing:

pear install Structures_Graph

This will yield an error once more, but you can see where the tar file is downloaded to. You can extract it manually and then copy the Structures directory into your PEAR directory (at the same level as the ‘Console’ directory). After that, you can

pear update pear

Once pear is up to date, configure it to auto discover channels. This is really important! And the next step is install phpunit.

pear config-set auto_discover 1
pear install --alldeps phpunit/PHPUnit

NOTE that for ZF 1.x you still need to specify the correct version of phpunit:

pear install --alldeps phpunit/PHPUnit-3.5.15
PHPStorm context menu detail
Run option in PHPStorm context menu

Last night I wanted to run a unit test for Zend Framework 1.11. I only recently switched from ZendStudio to PHPStorm and I didn’t yet run any PHPUnit unit tests from inside PHPStorm. I always liked running unit tests in ZendStudio, although this wasn’t always easy to setup, so I feared the new learning curve ahead of me. This wasn’t quite as hard as I imagined: like anything else in PHPStorm, it is easy to find and easy to setup. Just in case I forget how it all works, I write this down.

First of all, there are some differences in how PHPStorm and ZendStudio approach unit testing. In ZendStudio, you have to select ‘run as PHPUnit test’ from the context menu. The context menu is what you see when you click your right mouse button on the code you are editing and that is also the file that contains the unit test that you want to run. In PHPStorm, you just choose ‘Run’ from the context menu (see image).

Another option in the PHPStorm context menu is to setup a run configuration for the file. Once it is setup,  you will be able to select the run configuration from the menu bar and you get the opportunity to edit it as well. When setting up a run configuration, you can define the scope: Directory, Class,  Method or As Defined in the Configuration File, which is absolutely a great feature.

One of the things that will go wrong in ZendStudio is that you forget to include PHPUnit on the include path of your project, in which case ZendStudio cannot find the PHPUnit library. It will not tell you, it will just not run. PHPStorm will tell you it could not connect a testreporter if it can’t find PHPUnit. This is the exact error message: “Unable to attach test reporter to test framework or test framework quit unexpectedly”. In that case, you don’t have installed PHPUnit for the php version PHPStorm is using. In case you have several versions of php available on your system, you can configure which one PHPStorm should use. This is much the same as it is in ZendStudio. See the next image for how it is done in PHPStorm. In the same dialog, you can add entries to the include path for your php version. Make sure you add the path where PHPUnit lives (in my case that is “/Applications/MAMP/bin/php/php5.3.6/lib”).

Setting the php version in PHPStorm
Setting the php version in PHPStorm

One nifty little feature here is the little ‘i’ button, that brings up all ini settings if you click it. These are editable, but I did not check if that actually takes effect. To change the interpreter, you click the button with the three dots to select the path to your php. By clicking the ‘+’ button you can add entries to the include path.

Setting up PHPUnit

PHPUnit can be easily installed using PEAR. I once had this setup, but because I alwasy used ZendStudio, I had no need to keep it up and running an my installation had been broken by installing MAMP Pro over MAMP. I remembered that installing PHPUnit was a pain, because the pear installer that had shipped with MAMP was to old for the PHPUnit installation. Luckily, that problem did not re-occur.  I could easily install phpunit with pear, but I did no longer have the pear command. I broke that along with the same MAMP Pro installation.

Setup the pear command

To get the pear command back, the directory where it is located must be on your computers PATH. This is not the php include_path, but the PATH environment variable of your system. The PATH variable is set in your .profile file, that is located in your home directory. In my case, the home directory is /Users/bartmcleod. To edit the profile file, just open up terminal and type:

$s sudo vim /Users/bartmcleod/.profile

Inside .profile you will see something like:

export PATH=/opt/local/bin:/opt/local/sbin:$PATH

I changed that to:

export PATH=/opt/local/bin:/opt/local/sbin:/Applications/MAMP/bin/php/php5.3.6/bin:$PATH

to include the location where pear installs it’s commands. Once you have done this, you can proceed to install PHPUnit and you will also have the phpunit command available, since that goes into the same directory.

Installing PHPUnit for Zend Framework 1.x

You will think that installing PHPUnit with PEAR is easy: something along the lines of ‘sudo pear install phpunit’. Of course I tried that first and it executes and everything looks fine, except it didn’t really work for me. Then I found I had to type ‘sudo pear install phpunit/PHPUnit’. That worked, but it didn’t work with Zend Framework 1.x unit tests. They do not support PHPUnit 3.6. I found that the most recent version they support is PHPUnit 3.5.15. So I tried to uninstall phpunit and subsequently install that specific version, using the instructions I found here: http://stackoverflow.com/questions/1569012/how-to-install-an-older-version-of-phpunit-through-pear

In the same article however, it is specifically stated that to install 3.5.15, you have to uninstall separate phpunit components one by one, before installing the specific older version. If you don’t, pear will automatically detect that these components need the latest version and install that instead of the requested older version. This is annoying and hard to believe when you see it happen on the commandline. I had to try several times before I actually believed what was going on.

Because I did not want to type all the commands or paste them one by one, I just created two batch scripts. One to uninstall the latest versions and one to install the 3.5.15 versions.

Uninstall:

sudo pear uninstall phpunit/PHPUnit
sudo pear uninstall phpunit/DbUnit
sudo pear uninstall phpunit/PHP_CodeCoverage
sudo pear uninstall phpunit/File_Iterator
sudo pear uninstall phpunit/PHPUnit_MockObject
sudo pear uninstall phpunit/Text_Template
sudo pear uninstall phpunit/PHP_Timer
sudo pear uninstall phpunit/PHPUnit_Selenium
sudo pear uninstall pear.symfony-project.com/YAML

Re-install 3.5.15:

sudo pear install pear.symfony-project.com/YAML-1.0.2
sudo pear install phpunit/PHPUnit_Selenium-1.0.1
sudo pear install phpunit/Text_Template-1.0.0
sudo pear install phpunit/PHPUnit_MockObject-1.0.3
sudo pear install phpunit/PHP_Timer-1.0.0
sudo pear install phpunit/File_Iterator-1.2.3
sudo pear install phpunit/PHP_CodeCoverage-1.0.2
sudo pear install phpunit/DbUnit-1.0.0
sudo pear install phpunit/PHPUnit-3.5.15

The stackoverlow article from the above url gives more details and use cases that might apply to your particular situation, so if this set of commands doesn’t work for you, make sure you check the original post.

If unit testing with PHPUnit still doesn’t work from inside  PHPStorm

I upgraded to PHPStorm 4 and I tried to repeat the above procedure, and it didn’t work immediately. I kept getting the “Unable to attach test reporter to test framework or test framework quit unexpectedly” error message. I had to change the interpreter from php 5.4 (that ships with PHPStorm apparently) to php 5.3 local, like I had it set up before. I verified that the correct phpunit version is still installed, but with no luck. While trying again and again I found it seems to matter where you click inside the code. Clicking on a single test function will allow you to test only that function, while clicking on the class name will allow you to run the entire test class.

display_errors should be on (obviously)

While that is a nice feature, it doesn’t cover all the cases where unit testing doesn’t work. In one case for example, I had display_errors set to ‘off’ (accidentally) and if you do, you get the same error message  (“Unable to attach test reporter to test framework or test framework quit unexpectedly”) while you see nothing else that could help you detect the error.

Mind your slashes!

In yet another case with the same error message, I found I included the test superclass using windows (back)slashes as directory separators. Apparently, I had been developing those tests on a windows box and didn’t use forward slashes. The error message you get in that case is “Warning: require_once(PHPUnit\Framework\TestCase.php): failed to open stream: No such file or directory in …”. You might not notice immediately that the wrong  slashes are used if you run the tests on *nix or a Mac.