
Michael StrelanSenior Developer
Check out my detailed configuration for running and debugging tests via PHPStorm's PHPUnit integration with DDev and xdebug.
This post is a follow-up to recentblogposts, as well as improvements in PHPStorm and ddev.
The video below demonstrates how to configure everything you need to run and debug:
You can also checkout the ddev-phpunit-demo repo if you want to try it out yourself with DDev and PHPUnit pre-configured.
You may be able to achieve the same result with an alternative docker-compose environment, but I'm using DDev here since it mostly works out of the box.
In this section, Iāll share the final configuration Iām using. You can refer to the video above for an explanation of why some of these are needed.
All of these settings are found under the PHP section of the PHPStorm settings dialog. Before we start letās run ddev xdebug on to ensure the PHP extension is enabled.
UPDATE JANUARY 2022 - Since v1.18.2 ddev now ships its own docker-compose version. This defaults to v2 which still has some compatibility issues with PHPStorm. For now you can revert ddev's docker-compose version with the following command:
ddev config global --required-docker-compose-version=v1.29.2
--
For the most part DDev configures everything we need to use xdebug in PHPStorm. There are a few extra parts we need for running every kind of test. Fortunately, we can extend the generated docker-compose file by adding extra files in the .ddev directory. Add the following files then run ddev restart to regenerate the full docker-compose file.
docker-compose.env.yml
version: '3.6'
services:
web:
# DDev already sets this, add it here to debug Kernel tests.
# May be fixed by https://github.com/drud/ddev/pull/3149
environment:
- PHP_IDE_CONFIG=serverName=drupal.ddev.site
# Required for Drupal Test Traits. Will be fixed in ddev soon.
# @see https://github.com/drud/ddev/issues/3158
working_dir: /var/www/html
docker-compose.chromedriver.yml
version: '3.6'
services:
chromedriver:
container_name: ddev-${DDEV_SITENAME}-chromedriver
image: drupalci/chromedriver:production
labels:
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: $DDEV_APPROOT
external_links:
- ddev-router:${DDEV_SITENAME}.${DDEV_TLD}
web:
links:
- chromedriver:$DDEV_HOSTNAME
docker-compose.chrome.yml
version: '3.6'
services:
chrome:
container_name: ddev-${DDEV_SITENAME}-chrome
image: previousnext/chrome-headless:65
labels:
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: $DDEV_APPROOT
external_links:
- ddev-router:${DDEV_SITENAME}.${DDEV_TLD}
web:
links:
- chrome:$DDEV_HOSTNAME
It's best to refer to the video above for these, but some brief info below.
These should essentially ājust workā as they run in a single process with no database, you donāt even need to be listening for connections. Just make sure you have xdebug enabled (ddev xdebug on).
We need to make sure the database configured in SIMPLETEST_DB is accessible to the remote PHP interpreter. In ddev you can use mysql://db:db@db/db which is the internal connection string for the database, or for better performance use sqlite://localhost/sites/simpletest/db.sqlite
Kernel tests run in a separate PHP process which means PHPStorm has a harder time dealing with them. See KernelTestBase::runTestInSeparateProcess. To intercept the subprocess we need to make sure weāre listening for connections first. We also need to ensure the PHP_IDE_CONFIG env var is actually set in the subprocess. See the docker-compose.env.yml file that enforces this.
When you debug the test you will see the debugger pauses with two tabs, one for the Kernel test and one for āStandard input codeā, which is the subprocess. If you check the debug tab of the subprocess youāll see āCannot find a local copy of the file on server /var/www/html/web/Standard input codeā. You can ignore this and hit Resume, but itās easiest to prevent it breaking here in the first place. This is why we uncheck āForce break at first line when no path mapping specifiedā.
<env name="SIMPLETEST_BASE_URL" value="http://drupal.ddev.site"/
Again this needs to be accessible to the php interpreter. We could use the internal ddev hostnames however then our debug server configuration wonāt match up, so in this case we can use the ddev router. This is why the external_links part of the chromedriver service is important.
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value='["chrome", {"browserName":"chrome","chromeOptions":{"args":["--disable-gpu","--headless", "--no-sandbox"]}}, "http://chromedriver:9515"]'/
<env name="DTT_BASE_URL" value="http://drupal.ddev.site"/>
<env name="DTT_API_URL" value="http://chrome:9222"/>
<env name="DTT_MINK_DRIVER_ARGS" value='["chrome", {"browserName":"chrome","chromeOptions":{"args":["--disable-gpu","--headless", "--no-sandbox"]}}, "http://chromedriver:9515"]'/>