Executing PHPUnit tests in DDEV for Drupal projects.

My motivation to write this article was the lack of information out there regarding detailed process for setting up, writing and executing PHPUnit tests for Drupal on DDEV

Pasan Gamage
5 min readNov 7, 2024

In a previous article, I’ve explained how to set up your local machine to run Browser based tests locally. But today let’s look into how we can set up the necessary services inside a docker container, For this reason we will be utilising DDEV.

Prerequisites

Composer, Docker and DDEV installed locally.

Preparation

*Step 1*

I will be using my demo Drupal project https://github.com/pasankg/drupal-playground to demonstrate the DDEV setup and other relevant components.

First, let's clone the project using the terminal.

git clone git@github.com:pasankg/drupal-playground.git

and cd drupal-playground

Execute ddev config command.

You should see a .ddev folder in your project folder and inside there a file named config.yml and also settings.ddev.php file in web/sites/default/ path.

You can use the auto generated config.yml configurations, but give below is the config file that I use.

name: drupal-playground
type: drupal
docroot: web
php_version: "8.3"
webserver_type: nginx-fpm
xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
database:
type: mariadb
version: "10.11"
use_dns_when_possible: true
composer_version: "2"
web_environment: []
corepack_enable: false
nodejs_version: "20"

To spin up the DDEV environment, you need to have docker running on your local. Executing ddev start will start the build process. Once completed, you should see;

The settings.ddev.php gets regenerated everytime you restart the container, if you want to retain any custom code make sure to remove the comments at the top of the file.

/**
* @file
* This is a Drupal 11 settings.ddev.php file automatically generated by DDEV.
*
* DDEV manages this file and may delete or overwrite it unless this
* comment, marked with #ddev-generated, is removed. It is recommended
* that you leave this file alone.
*/

*Step 2*

Please note that I’ve already installed the following composer dev dependencies. And in my composer.json file under “require-dev” I have something like this.

"require-dev": {
"behat/mink": "^1.12",
"behat/mink-selenium2-driver": "^1.4",
"drupal/core-dev": "^11.0",
"phpspec/prophecy": "^1.19",
"phpspec/prophecy-phpunit": "^2.2",
"phpunit/phpunit": "^10.5"
}

For any other project, you can do the same and install the composer dev dependencies. The required ones are;

composer require --dev drupal/core-dev --with-dependencies
composer require --dev phpunit/phpunit --with-dependencies
composer require --dev behat/mink-selenium2-driver --with-dependencies

Execute ddev composer install to install dependencies inside the container.

To set up a fresh Drupal install, execute ddev drush si -y

*Step 3*

In order to execute Functional JavaScript tests, we need to have chrome selenium driver running on the background. For this, we can use DDEV Selenium Standalone Chrome from https://github.com/ddev/ddev-selenium-standalone-chrome

ddev add-on get ddev/ddev-selenium-standalone-chrome and ddev restart

If you check the .ddev folder, you may notice two new files are created.

config.selenium-standalone-chrome.yaml and

docker-compose.selenium-chrome.yaml

By default, you do not need to make any changes to the settings.ddev.php or to above config files.

*Step 4*

Now, let's create our phpunit.xml file. We can use a copy of the Drupal core phpunit.xml.dist file in web/core path. Copy it and paste in your project root. In this case I’ve already checked it in to the git repository so you will be able to see it there. It is a trimmed down version of the core phpunit.xml.dist file.

You may see some commented lines of code, these are to demonstrate that this file can be edited if you need it to be.

The main changes are updating the SIMPLETEST_BASE_URL value to

<env name=”SIMPLETEST_BASE_URL” value=”http://web"/> and updating the <testsuites> element according to the project. If you are wondering whathttp://web is, it is same as localhost in DDEV.

*Step 5*

Now that we have everything setup, let's execute an existing Functional test that I’ve created for a custom module playground_form

Functional test

Because the Functional test is executed on a fresh Drupal install, we do not need anything extra to test its functionality.

ddev exec -d /var/www/html/ “./vendor/bin/phpunit -c ./phpunit.xml ./web/modules/custom/playground_form”

Unit test

Now let’s try executing an existing Unit test, which also executes on a fresh Drupal install and not on the existing database.

ddev exec -d /var/www/html/ “./vendor/bin/phpunit -c ./phpunit.xml ./web/modules/custom/playground_address_search/tests/src/Unit”

--

--

Pasan Gamage
Pasan Gamage

Written by Pasan Gamage

Backend Developer | Motorbike enthusiast

No responses yet