Remote interpreter, run configs and coverage from the IDE
Running tests directly in the IDE with a single click or keyboard shortcut, without ever opening a console, is a productivity gain that quickly becomes second nature. PhpStorm supports PHPUnit for Docker-based Magento setups completely, as long as the remote interpreter and the run configuration are set up correctly. This article walks through the full setup process.
Table of Contents
- 1. Prerequisites and project structure
- 2. Setting up a Docker remote interpreter in PhpStorm
- 3. Configuring PHPUnit as the test framework in PhpStorm
- 4. Run configurations for different test suites
- 5. Enabling the coverage view in PhpStorm
- 6. Xdebug integration: debugging tests with breakpoints
- 7. Magento-specific considerations
- 8. Configuration variants compared
- 9. Summary
- 10. FAQ
1. Prerequisites and project structure
Before PhpStorm can be configured for PHPUnit in a Docker-based Magento project, a few prerequisites need to be in place. The Docker container with the PHP interpreter must be running and reachable from PhpStorm. The Magento source code must be correctly opened as a project in PhpStorm, either directly on the filesystem or through an SSH-based remote development environment. PHPUnit must be installed as a Composer dependency so that vendor/bin/phpunit is available inside the container.
For the Mark Shust Docker setup used in this project, the relevant container is phpfpm with PHP 8.4 and the Magento source code under /var/www/html. The source code on the host lives under src/ and is mounted into the container. PhpStorm accesses the phpfpm container through the Docker interpreter. The phpunit.xml file sits at the project root under src/. This structure is the foundation for every configuration step that follows.
2. Setting up a Docker remote interpreter in PhpStorm
The remote interpreter connects PhpStorm to the PHP binary inside the Docker container. Without this step, PhpStorm cannot run any tests inside the container. Configuration happens under Settings → PHP → Interpreters → (+) → From Docker, Vagrant, VM, WSL, Remote. In the Configure Remote PHP Interpreter dialog, choose Docker as the connection type and the Docker server (usually Unix socket on Linux or Docker for Mac on macOS). Select the PHP image that is also used for the phpfpm container.
Once configured, PhpStorm displays the PHP version of the remote interpreter and checks whether PHP is reachable. A common problem: the Docker container must be running when PhpStorm tests the interpreter. When using docker compose, the stack must already be started with bin/start or docker compose up -d phpfpm. The interpreter name should be meaningful, e.g. Docker PHP 8.4 (phpfpm), since it gets referenced later in run configurations.
# Directory structure for PhpStorm configuration (Mark Shust setup)
# Host path -> container path (volume mapping)
#
# Host: ~/development/mironsoft/src/
# Container: /var/www/html/
#
# This mapping must be entered in PhpStorm under
# Settings -> PHP -> Interpreters -> (Remote Interpreter) -> Path Mappings:
#
# Local path: /home/mir/development/mironsoft/src
# Remote path: /var/www/html
# Relevant containers in the Mark Shust setup:
# phpfpm - PHP 8.4, Composer, PHPUnit
# db - MySQL for integration tests
# redis - cache (optional for tests)
# Check after interpreter setup in PhpStorm:
# Settings -> PHP -> Interpreter shows PHP 8.4.x (Docker)
# vendor/bin/phpunit --version returns PHPUnit 11.x
One important detail: path mappings must be configured correctly. PhpStorm sends the local file path to the remote interpreter, which needs to know the corresponding container path. The path mapping tells PhpStorm that /home/mir/development/mironsoft/src on the host corresponds to /var/www/html inside the container. Incorrect path mappings cause PhpStorm to fail to locate test files, or to map coverage information onto the wrong lines.
3. Configuring PHPUnit as the test framework in PhpStorm
After setting up the interpreter, PHPUnit needs to be registered as a test framework. Configuration happens under Settings → PHP → Test Frameworks → (+) → PHPUnit by Remote Interpreter. In the dialog, select the remote interpreter you just configured and provide the path to the PHPUnit autoloader file: /var/www/html/vendor/autoload.php (container path). Optionally, the phpunit.xml can be specified as the default configuration: /var/www/html/src/phpunit.xml, or wherever it lives depending on project structure.
After the configuration, PhpStorm attempts to start PHPUnit through the remote interpreter and read out the version. On success, it shows PHPUnit 11.x or whatever version is installed. On failure, the usual culprit is either the container not being started, an incorrect path mapping, or an incorrect autoloader path. The debug output in PhpStorm's Event Log panel contains details about the failed connection attempt.
<!-- phpunit.xml - configuration for PhpStorm integration (Magento 2.4) -->
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
cacheDirectory=".phpunit.cache"
executionOrder="defects,duration"
>
<testsuites>
<testsuite name="unit">
<directory>app/code/Mironsoft</directory>
<exclude>app/code/Mironsoft/*/Test/Integration</exclude>
</testsuite>
<testsuite name="integration">
<directory>app/code/Mironsoft</directory>
<include>app/code/Mironsoft/*/Test/Integration</include>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">app/code/Mironsoft</directory>
</include>
<exclude>
<directory>app/code/Mironsoft/*/Test</directory>
</exclude>
</source>
<!-- bootstrap is overridden per run configuration -->
</phpunit>
4. Run configurations for different test suites
Run configurations in PhpStorm let you save different PHPUnit setups as reusable configurations that run with a single click or keyboard shortcut. For a Magento project, at least two configurations are recommended: one for unit tests (fast, no database access) and one for integration tests (slower, with Magento bootstrap and database access).
A new run configuration is created via Run → Edit Configurations → (+) → PHPUnit. The key fields: Test runner selects the remote interpreter; Test scope can be set to Defined in configuration file with the corresponding phpunit.xml, or to Suite with the name of the desired suite. The Environment variables section lets you set environment variables for the test run, for example XDEBUG_MODE=off for fast runs without debugging. For the Magento integration test bootstrap, MAGENTO_BOOTSTRAP=1 can be entered as an environment variable and evaluated inside the bootstrap script.
5. Enabling the coverage view in PhpStorm
PhpStorm visualizes coverage data directly in the editor: lines covered by tests appear highlighted in green, uncovered lines in red. To enable this view, the run configuration must be started with Run with Coverage (the shield icon next to the run button). PhpStorm derives the coverage information from the PHPUnit output and displays it in the affected files immediately after the test run.
A prerequisite for coverage in PhpStorm with the Docker interpreter: either pcov or Xdebug must be installed and correctly configured in the container. With pcov: set XDEBUG_MODE=off as an environment variable in the run configuration and make sure pcov is enabled in the container's PHP configuration. With Xdebug: set XDEBUG_MODE=coverage. Coverage results are listed by class and method in PhpStorm's Coverage tool window and can be exported as an HTML report.
6. Xdebug integration: debugging tests with breakpoints
One of the biggest advantages of the PhpStorm integration is being able to debug tests with breakpoints. When a test fails and the cause is not obvious, debugging lets you inspect the state of every variable at any point during execution. This requires Xdebug to be configured and reachable inside the container.
In the Mark Shust setup, Xdebug is enabled via bin/xdebug enable. PhpStorm listens on port 9003 by default for incoming Xdebug connections. Under the PHP → Debug settings, make sure Xdebug is selected as the debug extension and port 9003 is configured. Start the run configuration for debugging with the Debug button (the bug icon). PhpStorm stops execution at every breakpoint you have set and shows variable values, the call stack and the current execution context.
<?php
// Example test for debugging with PhpStorm breakpoints
declare(strict_types=1);
namespace Mironsoft\Catalog\Test\Unit\Service;
use Mironsoft\Catalog\Service\TaxCalculator;
use PHPUnit\Framework\TestCase;
final class TaxCalculatorTest extends TestCase
{
private TaxCalculator $calculator;
protected function setUp(): void
{
$this->calculator = new TaxCalculator(defaultRate: 0.19);
}
/**
* Set a breakpoint on the next line in PhpStorm,
* then run this test with the Debug button (Shift+F9).
* PhpStorm will stop here and show all variable values.
*/
public function testCalculatesTaxForStandardRate(): void
{
$result = $this->calculator->calculate(netAmount: 100.0); // <- Breakpoint here
// Inspect $result in the Debug tool window before this assertion
$this->assertSame(119.0, $result);
}
public function testReturnsZeroForZeroAmount(): void
{
$result = $this->calculator->calculate(netAmount: 0.0);
$this->assertSame(0.0, $result);
}
}
7. Magento-specific considerations
Magento integration tests have a few peculiarities that affect PhpStorm configuration. Magento's own test bootstrap (dev/tests/integration/framework/bootstrap.php) initializes the object manager, establishes database connections and configures the store. This bootstrap must be correctly referenced in the phpunit.xml for integration tests. For unit tests, the Composer autoloader is sufficient.
Another Magento-specific point: Magento's integration test framework expects environment variables such as TESTS_CLEANUP and MAGENTO_MEMORY_LIMIT_FOR_SETUP to be set. These are entered as environment variables in the run configuration. Additionally, database credentials for the test database must be available for integration tests, usually via a phpunit.xml.dist in the Magento integration test directory, which is overridden with project-specific values.
| Configuration | Suite | Bootstrap | XDEBUG_MODE |
|---|---|---|---|
| Mironsoft Unit | unit | vendor/autoload.php | off |
| Mironsoft Unit + Coverage | unit | vendor/autoload.php | coverage (pcov) |
| Mironsoft Integration | integration | Magento Bootstrap | off |
| Debug (Unit) | unit (Filter) | vendor/autoload.php | debug |
| Current test (Cmd+Shift+F10) | File/class/method | phpunit.xml default | off |
9. Summary
Configuring PHPUnit in PhpStorm for a Docker-based Magento project requires several steps that build on each other: a remote interpreter with correct path mapping, PHPUnit framework registration with the container autoloader path, separate run configurations for unit and integration tests, and correct Xdebug configuration for debugging. Once the configuration is done, tests can be run with a single click or keyboard shortcut.
The most important practical tip: create separate run configurations for fast unit tests and slow integration tests. In everyday development work, the unit test configuration is used most, it runs in seconds and gives immediate feedback. The integration configuration is used less often but is indispensable for full validation before a commit. The coverage view in PhpStorm makes test gaps immediately visible and motivates covering critical code paths.
PHPUnit in PhpStorm for Magento, the essentials at a glance
Remote interpreter
Settings -> PHP -> Interpreters -> Docker. Path mapping: local src/ path -> /var/www/html in the container. Container must be running.
Test framework
Settings -> PHP -> Test Frameworks -> PHPUnit by Remote Interpreter. Autoloader: /var/www/html/vendor/autoload.php.
Run configurations
Separate configurations for unit (fast, no bootstrap) and integration (Magento bootstrap, DB). XDEBUG_MODE as an env variable.
Coverage & debug
Run with Coverage for green/red highlighting in the editor. Debug button for breakpoint debugging. bin/xdebug enable before debug runs.