I'm trying to run my PHPUnit tests from my Docker container within PHPStorm. Currently, I've provisioned both a Docker instance and CLI interpreter in PHPStorm, but PHPStorm is unable to open phpunit in my Docker container, complaining. Tutorial to set up PhpStorm for local PHP web development using Docker containers, Apache webserver, MySQL database, and PHPUnit testing framework for your P.
I like using docker containers to keep PHP separate from my host machine which allows for easy switching of version.
I really like PhpStorms quick menu for running tests or scripts so I set it up to work with docker containers.
Things you will need:
- PhpStorm
- A docker container with PHP on it
- A project with PHPUnit tests
First we need to set up a remote interpreter. PHPStorm doesn’t support docker’s exec function to run remote PHP scripts (yet) so we’ll have to use SSH.
If you’re making your own Dockerfile install openssh-server and add a user:
If it’s already on your container image just add the user. Now would be a good time to test SSH. You’ll need to map port 22 to make it accessible.
Another handy thing is to make sure your container will have a static ip so you won’t have to check it every time. You’ll need to create a docker subnet first with:
docker network create --subnet=172.18.0.0/16 dockernet
Then run your container:
docker run -it -v $PWD:/var/www -p 22:22 --net dockernet --ip=172.18.0.2 my-image-name /bin/bash
Start the ssh service with service ssh start
and you should be able to connect to it from your host with ssh php-remote@172.18.0.2
(using the password you created above).
If you don’t like the interactivity of starting ssh yourself you could create an image with php-cli that runs sshd.
Alright, alright. Hopefully you have a running container that you can access from SSH.
Next inside PhpStorm go to “Settings > Languages & Frameworks > PHP” and click on the ‘…’ next to Interpreter.
Click the green plus icon to add a new one and select remote. Choose “SSH Credentials” and enter the ip address, username and password. If it all works it should auto detect the version.
Next let’s set up the PHPUnit configuration.
From “Settings > Languages & Frameworks > PHP > PHPUnit” click the plus icon and select “By Remote Interpreter”, then choose the interpreter you just set up.
If you’re mounting your project in your container set your path mappings.
You’re free to chose which method to use for loading PHPUnit here. Personally I like to load it from the composer autoloader since it’s easy to change version (and sometimes you don’t want to break all your tests for an old project by updating PHPUnit globally).
Last step is to set up the run configuration. From the top right of your PhpStorm window select the little drop-down arrow and choose “edit configurations”.
Click the green plus to add a new one and choose PHPUnit. Choose to use an alternative configuration file and point to your phpunit.xml. You can use the path on your host machine here as PhpStorm is clever enough to replace it with the path mappings you chose.
Give your configuration a fancy name and you should be good to go.
I wanted to run tests with PHPUnit on a docker environment, which was set up with docker-compose, and use the PhpStorm integration. Since PhpStorm 2013.2 there is a docker intergration which works well for single containers, but unfortunately it does not seem to use the running network of containers. So for example my PHP container does not get access to the MySQL container for integration tests.
If that’s not a problem for you, you will not need what I am going to explain here, read this instead: https://blog.jetbrains.com/phpstorm/2016/11/docker-remote-interpreters/
Local CLI Interpreter
So instead of configuring the Remote PHP Interpreter for Docker, I created a local interpreter like this and selected it as the CLI interpreter for the project:
The interpreter is actually a shell script that runs PHP in my container using docker-compose run
. PhpStorm will not know that it runs in a container. I got the idea from this article and adapted it for docker-compose.
This is the test.sh
script:
Where “integration” is the name of the container.
docker-compose Configuration
For me the “integration” container is defined like this in docker-compose.yml
:
Yours will look different, whatever the needs of your PHP container are. But the two highlighted lines that are important for the PhpStorm integration:
- PhpStorm writes a temporary test runner to
/tmp
, so we mount the host /tmp directory to the container - The project directory must be mounted to the exact same path as on the host because there are no path mappings for a local interpreter and host paths will be passed to PHPUnit
Integrate the Test Runner
Now when you run a test file, or a phpunit.xml
configuration in PhpStorm, the path is passed to our fake interpreter (test.sh) and …
Cannot find PHPUnit in include path
This error caused me some headache. I finally found out that the test runner that is generated by PhpStorm looks for “../../vendor/autoload.php” or “../../../vendor/autoload.php” within the include path. I’m not sure why it works like this, it seems to assume that it is run with the directory of the “phpunit” executable as working directory. Since “.” is usually in the include path, it finds the correct composer autoloader from there.
On the docker container this is not the case (the working directory on the host does not matter here). I tried to change the working directory there but in the end it was easier to change the include path in the “Run/Debug Configuration”:
Interpreter options:
Now it works!
Phpunit Setup
PhpStorm runs the command like this:
which results in this command being executed on the container:
Phpunit Xdebug Phpstorm Docker
If you mounted the paths correctly and the container is running, the tests will run on the container and PhpStorm “thinks” they run locally.