Debug Unit Tests using the PhpStorm built-in test runner

PhpStorm comes with a handy phpunit test runner, which lets you execute your tests with just one click. Even better: if a test fails, you can just run that test also with just one click. That’s how I like it.

However I often use the debugger to debug failed tests. This is easy with phpunit and via the command line (see e.g. Remote CLI debugging). But since PhpStorm is obviously not using the command line, we have to pass the information necessary for Xdebug and PhpStorm to initiate the debug session using the Test Runners configuration.

XDEBUG_CONFIG=idekey=PHPSTORM ; PHP_IDE_CONFIG=serverName=local.dev

Needless to mention that the above values need to fit your setup. Most likely your server name will be different, and make sure to check the ide key.

But where to put it? Assuming you already setup your Run/Debug configuration, just open the configuration dialog and put the above environment variables into the “Environment variables” input field. You don’t need to add “export” or anything. Well, just have a look:

phpstorm_unit_test_runner

Now just place your breakpoints as you need them and start the Run/Debug configuration.

Debug your Codeception tests with Xdebug and PhpStorm

I use Xdebug not only to hunt bugs, but also for every day development work. Of course I also want to use it when I write my Tests.

I one of my current projects we use Codeception for both Unit- and Acceptance tests. Debugging Codeception Unit tests is as easy as for phpUnit, you just have to make sure that the XDEBUG_SESSION is set as described in my post about CLI debugging with Xdebug.

What to test

The Acceptance tests I want to debug are basically just testing a REST API, so it’s usually firing HTTP GET/POST requests against various endpoints:

class ApiCest
{
    public function testDoStuff(ApiTester $I)
    {
        $I->sendPOST('/my/api/dostuff');

        // testing starts here
        $I->seeResponseCodeIs(200);
    }
}

In order to debug the actual “dostuff” endpoint, I have to take care of two things: the debug session Cookie and the PhpStorm debug configuration.

Set the XDEBUG_SESSION cookie

The usual way for me to start a PhpStorm session for non-CLI scripts is to enable the “Start Listening for PHP Debug Connections” in PhpStorm and initiate a request with the XDEBUG_SESSION cookie set.

I’m assuming you have PhpStorm and Xdebug set up neat and nicely, as there are enough tutorials about it out there.

This works nicely when I start a debug session using the browser, but now we don’t use a browser and send the requests via HTTP directly (Codeception uses Guzzle for that), so we have to set the Cookie somehow. There are (at least) three ways to do that with Codeception:

  1. Set the cookie manually in the Cest (Codeception acceptance test class)
    $I->setCookie('XDEBUG_SESSION', 'PHPSTORM');
    
  2. Configure Guzzle to send the Cookie via the codeception.yml

    This is described Codeception manual on the PhpBrowser module

  3. Use the codeception/remote-debug extension

    Codeception-Remotedebug on Github

    This is my preferred way, it’s actually pretty easy to set up, and this way I just send the Cookie all the time.

    extensions:
      enabled:
        - Codeception\Extension\RemoteDebug
        config:
          Codeception\Extension\RemoteDebug:
            sessionName: PHPSTORM
    
    Since the Cookie value (PHPSTORM) might be different for other developers, these settings should not be under Version control. Codeception allows several ways to achieve this, in our project we use a environment-specific setup, which is not under version control and allows use to extend or overwrite settings on the project-wide, version controlled codeception.yml. Learn more about it in the Codeception manual on Environments.

    Increase PhpStorms Max. connections

    This might cause some headache if you forget about it. When I tried to all of the above ways to set the Cookie, the debug session was always getting stuck, i.e. PhpStorm was not stopping at the breakpoints and rather did – nothing!

    phpstorm_debug_max_connections

    By default, PhpStorm is configured to handle 1 debug session at a time. However in my case, I need to handle 2 debug sessions in parallel now – one debug session for the actual Acceptance test, and one for the API.

    And that’s it. I hope this will be useful for other Codeception users as well!

Debugging Flow3 – ain’t got time for that!?

It is known that XDebug has a negative impact on performance, but what happens when you try to debug a Flow3 application can be something between absolutely surprising and totally annoying. But one after another.

XDebug is my every day tool. I use it not only for debugging, but for regular development as well. I simply enjoy the benefit to always know which variables are available in the current scope (Typo3 globals, anyone?), I don’t need to recall nested array structures, I can evaluate my code on the fly and so on. So naturally, on my dev XDebug is always enabled and listening, both for PHP SAPI or Webserver.

Working on my first Flow3 project, I suddenly found myself waiting over 30 minutes for the Cache to rebuild after flushing it manually. Running the application on a different machine worked ok, so it was obvious that the issue was somewhere in my setup. Wtf?

So I did what a normal XDebug user would do – let’s profile that damn thing! I realized the core problem as I found dozends of sometimes quite huge Cachegrind files in my output directory. What the heck, there must be really some serious action going on (and it does – see box below)! So I disabled XDebug for the moment, and voilà – the Cache was rebuild within seconds.

If you have not worked with Flow3 before you have to know that Flow3 actually requires cached class files because of the use of Aspect-oriented programming (AOP). In short, Flow3 scans the code files of the packages whether certain rules (the so called Aspects, defined via Annotations) apply, and changes the code in the classes according to the Aspect. Doing this for every request would be obviously insane, so the results are cached. We suddenly find our good old PHP scripts in some way being compiled.

There is a nice article about Flow3 and AOP to be found here which describes it more in detail.

Flow3 luckily has some advanced file monitoring which, when you work in Development context, makes it unnecessary to clear the whole cache manually every time you change a class, and rebuilding the cache for one class only will work within a reasonable amount of time even with XDebug turned on. Nevertheless sometimes you will need to flush the whole cache, and then you’re doomed. En-/Disabling XDebug in the php.ini manually would be too cumbersome (for me). So there has to be a more convenient solution.

How to debug Flow3 applications and stay sane

Here’s with what I ended up: I disabled XDebug for PHP via CLI by default, and enable it only when I need it using the “php -d” switch:

php -dxdebug.remote_autostart=On -dxdebug.remote_enable=On ./flow

Not a very easy one to remember, but we’re getting close. Why not put this into a separate shell script? Yes, why not. I called it “flowdebug”, and it is located in the project root (where the original flow command is located).

#!/bin/sh
export PHP_IDE_CONFIG="serverName=my.server"
export XDEBUG_CONFIG="idekey=PHPSTORM"
php -dxdebug.remote_autostart=On -dxdebug.remote_enable=On ./flow "$@"

As you can see I also put the environment variables needed to start the debugging session in that script.

So from now on, when I want to debug my Flow3 application, I simply use

./flowdebug mypackage:mycommand