Drupal core development offers developers both opportunities and challenges. On the one hand, it keeps them updated with the latest API changes, ensures their skills stay sharp, introduces fresh ideas and solutions by reviewing contributions from other smart developers and helps developers optimize their code for various scenarios they might not have considered before.

On the other hand, getting into Drupal development isn’t easy. Setting up Drupal correctly requires attention to detail and understanding its setup. Developers also need to run checks locally or rely on continuous integration systems to validate their code, which can take time.

The aim of this guide is to assist new developers in setting up and understanding how to run the tests mentioned earlier.

This guide is divided into three main sections for new developers tackling Drupal core development. It starts with installing Drupal correctly to set up a stable environment. The second section covers running tests and using essential tools, focusing on local checks and leveraging continuous integration for code validation. Finally, we’ll explore other alternatives and their tradeoffs.

Installing Drupal

For Drupal, you’ll need both a web server and a database to function properly. The web server handles requests and serves Drupal’s pages, while the database stores the site’s content and configuration.

One of the most convenient ways to install Drupal is using DDEV. DDEV simplifies the setup process by providing a Docker-based environment that includes all necessary dependencies, making it easy to develop and deploy Drupal projects quickly and consistently.

DDEV also facilitates easy switching between MySQL, PostgreSQL, and SQLite, making it straightforward to develop Drupal contributions across different database environments. This flexibility supports developers in testing and optimizing their code for diverse deployment scenarios.

git clone https://git.drupalcode.org/project/drupal.git drupal
cd drupal/
ddev config --project-type=drupal
ddev start
ddev composer install

The commands above initiate the process of cloning and preparing Drupal for installation.

We will utilize justafish/ddev-drupal-core-dev to access helpful commands that streamline development tasks. This tool provides utilities tailored for Drupal core development, simplifying tasks such as running tests, managing dependencies, and maintaining development environments efficiently.

ddev get justafish/ddev-drupal-core-dev
ddev restart

Please note that there is a deliberate reason for not following the exact steps outlined in the README provided by justafish/ddev-drupal-core-dev, as it enables the execution of MySQL-related tests. See more database if you want to use Sqlite or Postgresql.

The primary challenge when installing Drupal is ensuring the repository remains unaltered by local changes, such as installing Drush. justafish/ddev-drupal-core-dev provides a Drupal install command that avoids the need to install Drush. However, this command does not work well with the way ddev configures the settings.php file. But, you can install Drupal using the user interface (UI).

ddev launch
## Install the site using the UI
git status
Your branch is up to date with 'origin/11.x'.

We have successfully installed Drupal, and the repository remains unchanged and ready for commit.

Drupal successfully installed

How To Reinstall?

Since we don’t have drush available, you can reinstall Drupal by deleting the database and using the Drupal UI.

ddev delete -Oy
ddev restart
ddev launch

And complete the UI to install Drupal.

Making Changes And Running Tests

For simplicity, let’s assume you already know what you want to modify in Drupal core.

You create a new branch using this guide.

When contributing to Drupal, one frustration is waiting half an hour to realize you made a typo in a PHP file. So, let’s explore how we can avoid that.

Running PHPCS

Since we’re using ddev, we now have access to the following command: ddev composer. Imagine you’re making changes to the Image module.

ddev composer phpcs core/modules/image will detect PHP issues in this folder using PHP CodeSniffer.

To fix issues found you can run:

ddev composer phpcbf core/modules/image
Fixing errors automatically using PHP Code Sniffer.

Checking Typos

If you’re writing code, it’s common to have some typos.

ddev yarn run spellcheck modules/image/ will search for typos in the modules/image/ directory using the spellcheck feature.

Please note that you need to be inside the core directory to run this command.

Drupal spell check in action

Running Tests

Drupal employs several types of tests to ensure robust functionality:

  1. Unit Tests: These tests validate small, isolated units of code, typically functions or methods.
  2. Kernel Tests: Kernel tests verify the integration of modules and how they interact with Drupal’s core systems.
  3. Functional Tests: Functional tests simulate user interactions with the Drupal site, testing features like form submissions, user logins, and content creation.
  4. JavaScript Functional Tests: These tests validate JavaScript behavior and interactions within Drupal.
  5. Nightwatch Tests: Nightwatch Drupal tests typically involve scripting test scenarios that simulate real user behavior, such as navigating pages, filling out forms, and verifying expected outcomes.

The first four types of tests can be executed using PHPUnit with the following command: ddev phpunit core/module/image. This command runs PHPUnit tests specifically for the core/module/image directory, covering unit, kernel, and functional tests within that module.

PHPunit running tests.

For Nightwatch tests, we can leverage the capabilities provided by justafish/ddev-drupal-core-dev.

NoVNC connection displaying nightwatch tests.
ddev nightwatch modules/navigation/tests/src/Nightwatch/Tests/expandCollapseTest.js

Note the missing core/ in the last command.

And when running the tests you can view real-time tests using the NoVNC extension.

ddev launch :7900
## the password is: secret

How Do I Know Which Test To Run?

As Drupal evolves, more tests and automated checks can be added to the pipeline. You can inspect the GitLab pipeline to see which steps are running and figure out which commands you need to run locally to replicate the results.

Different tests run by the GitLab CI pipelines

Debugging

When writing Drupal tests, debugging is often essential to identify failures. Enabling ddev xdebug on sets up the PHP debugger quickly, making it easier to diagnose issues and streamline the testing process. Read the documentation for different IDEs.

ddev xdebug on

Will enable the debugger. You can configure this in VS Code or PHP Storm. It’s recommended not to run tests with xdebug enabled unless actively debugging, as it can slow down test performance.

Visual Studio Code debugging a Drupal core test execution.

More Databases

So far all the examples covered MariaDb. If you want to use PostgreSQL, you can leverage ddev config.

ddev delete -Oy
# Set a different DB engine.
ddev config --database=postgres:16
ddev start

And reinstall Drupal using the UI.

There is only one change you need to apply to core/phpunit.xml Replace mysql:// with pgsql:// in

    <env name="SIMPLETEST_DB" value="pgsql://db:db@db/db"/>

And you will be able to run the tests using the PostgreSQL database server.

PostgreSQL running in ddev

If you want to use Sqlite, there is no need to restart the container. Modify the core/phpunit.xml file with this config:

    <env name="SIMPLETEST_DB" value="sqlite://localhost/sites/default/files/db.sqlite"/>

Alternatives

So far we explored ddev, justafish/ddev-drupal-core-dev and cloning Drupal core directly from GitLab as the main option.

The main trade-off of this approach is that as soon as you try to install an extra package, such as Drush, the entire repository structure will be contaminated.

One alternative is to use: https://github.com/joachim-n/drupal-core-development-project which can also be integrated with justafish/ddev-drupal-core-dev.

However, this approach requires a bit more of reading and configurations. As the main repo is under repos/drupal but the installed packages live outside.

If you need a contrib module while developing Drupal core or rely heavily on drush (such as to generate code) then give the Joachim approach a try.

mariano's profile

Mariano D'Agostino

@dagmar