Running PHPUnit tests in Lando

Last updated on
30 July 2025

This page has not yet been reviewed by PHPUnit in Drupal maintainer(s) and added to the menu.

There are a couple options for configuring PHPUnit and running PHPUnit tests in Lando.

Preconfigured tooling for Lando+Drupal+PHPUnit

Custom tooling

Alternatively, if you simply want to run PHPUnit and have no need for everything else, you can setup a custom Lando tooling command.

PHPUnit 9 + Drupal 10

With this configuration, every time you run lando phpunit path/to/test.php, phpunit.xml will be recreated and configured for your project at core/phpunit.xml. Since core/phpunit.xml is deleted every time you update Drupal core via Composer, without this script you would need to configure core/phpunit.xml manually every time you update core.

Modify .lando.yml to include this:

.lando.yml

services:
  appserver:
    overrides:
      environment:
        # PHPUnit configuration. Sometimes the configuration in phpunit.xml is ignored.
        SIMPLETEST_BASE_URL: "http://mysite.lndo.site"
        SIMPLETEST_DB: "mysql://username:password@landodatabaseservicename/databasename"
        # Note the URL here must correspond to the name of the service.
        MINK_DRIVER_ARGS_WEBDRIVER: '["chrome", {"browserName":"chrome","goog:chromeOptions":{"w3c":false, "args":["--disable-gpu","--headless", "--no-sandbox", "--disable-dev-shm-usage"]}}, "http://selenium-chrome:4444/wd/hub"]'
  selenium-chrome:
    type: compose
    app_mount: false
    services:
      image: seleniarm/standalone-chromium:101.0-20220429
      environment:
        TZ: America/Los_Angeles
        START_XVBF: "false"
      volumes:
        - /dev/shm:/dev/shm
      command: /opt/bin/entry_point.sh
tooling:   
  phpunit:
    service: appserver
    cmd:
      - /app/lando/scripts/phpunit.sh

Create this .sh file. The directory structure is optional, but it must be reflected in .lando.yml.

lando/scripts/phpunit.sh

#!/usr/bin/env bash

ARGS="$@"

# Based on: https://www.drupal.org/docs/develop/automated-testing/phpunit-in-drupal/running-phpunit-tests#s-configure-phpunit

# Copy Drupal core phpunit config.
cp /app/web/core/phpunit.xml.dist /app/web/core/phpunit.xml

# Configure it for Lando.
sed -i 's/<env name=\"SIMPLETEST_BASE_URL\" value=\"\"\/>/<env name=\"SIMPLETEST_BASE_URL\" value=\"http:\/\/mysite\.lndo\.site\"\/>/' /app/web/core/phpunit.xml
sed -i 's/<env name=\"SIMPLETEST_DB\" value=\"\"\/>/<env name=\"SIMPLETEST_DB\" value=\"mysql:\/\/username:password@landodatabaseservicename\/databasename\"\/>/' /app/web/core/phpunit.xml
sed -i 's/<env name=\"BROWSERTEST_OUTPUT_BASE_URL\" value=\"\"\/>/<env name=\"BROWSERTEST_OUTPUT_BASE_URL\" value=\"http:\/\/mysite\.lndo\.site\"\/>/' /app/web/core/phpunit.xml

# Support Drupal 11 where BROWSERTEST_OUTPUT_DIRECTORY does not exist in phpunit.xml.dist.
# Instead there is <parameter name="outputDirectory".
sed -i 's/sites\/simpletest\/browser_output/\/app\/web\/sites\/simpletest\/browser_output/' /app/web/core/phpunit.xml
# Support Drupal 10 where BROWSERTEST_OUTPUT_DIRECTORY exists in phpunit.xml.dist.
sed -i 's/<env name=\"BROWSERTEST_OUTPUT_DIRECTORY\" value=\"\"\/>/<env name=\"BROWSERTEST_OUTPUT_DIRECTORY\" value=\"\/app\/web\/sites\/simpletest\/browser_output\/\"\/>/' /app/web/core/phpunit.xml

sed -i 's/<env name=\"MINK_DRIVER_ARGS_WEBDRIVER\" value='\'''\''\/>/<env name=\"MINK_DRIVER_ARGS_WEBDRIVER\" value='\''\[\"chrome\", {\"browserName\":\"chrome\",\"goog:chromeOptions\":{\"w3c\":false, \"args\":\[\"--disable-gpu\",\"--headless\", \"--no-sandbox\", \"--disable-dev-shm-usage\"\]}}, \"http:\/\/selenium-chrome:4444\/wd\/hub\"\]'\''\/>/' /app/web/core/phpunit.xml

# Make output directory if it doesn't exist and set permissions.
mkdir -p /app/web/sites/simpletest
chmod -R 777 /app/web/sites/simpletest
mkdir -p /app/web/sites/simpletest/browser_output
chmod -R 777 /app/web/sites/simpletest/browser_output
# Delete previous results.
rm -f /app/web/sites/simpletest/browser_output/*.html
rm -f /app/web/sites/simpletest/browser_output/*.counter

# Run phpunit using Drupal core config.
/app/vendor/bin/phpunit -c /app/web/core $ARGS

Modify both files like this:

  • Replace "username" with your MySQL database username.
  • Replace "password" with your MySQL database password.
  • Replace "landodatabaseservicename" with the name of your MySQL database service. When using some Lando plugins this is "database".
  • Replace "databasename" with the your MySQL database name.
  • Replace "mysite" with the name of your Lando project.
  • Replace "web" with "docroot" if necessary.

Rebuild containers in order for changes to .lando.yml to take effect:

lando rebuild

Then run PHPUnit like this:

lando phpunit path/to/test.php

PHPUnit 10 + Drupal 11

Model .lando.yml file

name: drupal-core-development-project
recipe: drupal11
config:
  composer_version: 2
  webroot: web
services:
  chrome:
    type: compose
    services:
      image: drupalci/webdriver-chromedriver:production
      command: chromedriver --log-path=/tmp/chromedriver.log --no-sandbox --headless --verbose --whitelisted-ips= --allowed-origins=*
  appserver:
    build:
      - mkdir -p $LANDO_WEBROOT/sites/simpletest/browser_output
      - cp web/sites/default/default.settings.php web/sites/default/settings.php
      - echo '\r\n$databases["default"]["default"] = [
        \r\n  "database" => "drupal11",
        \r\n  "username" => "drupal11",
        \r\n  "password" => "drupal11",
        \r\n  "prefix" => "",
        \r\n  "host" => "database",
        \r\n  "port" => "3306",
        \r\n  "isolation_level" => "READ COMMITTED",
        \r\n  "driver" => "mysql",
        \r\n  "namespace" => "Drupal\\mysql\\Driver\\Database\\mysql",
        \r\n  "autoload" => "core/modules/mysql/src/Driver/Database/mysql/",
        \r\n];' >> web/sites/default/settings.php
      - echo '\r\n$settings["hash_salt"] = "1234567890";' >> web/sites/default/settings.php
    overrides:
      # Changes only take effect after `lando rebuild`
      environment:
        # See https://agile.coop/blog/drupal-phpunit-tests-lando/
        # Based on https://github.com/lando/lando/pull/1092/files
        # See also https://github.com/lando/lando/issues/360
        SYMFONY_DEPRECATIONS_HELPER: 'disabled'
        SIMPLETEST_DB: 'mysql://drupal11:drupal11@database/drupal11'
        BROWSERTEST_OUTPUT_BASE_URL: 'http://drupal-core-development-project.lndo.site'
        # Note: SIMPLETEST_BASE_URL must currently be defined in the phpunit.xml file
        # --disable-dev-shm-usage is needed to allow iframed content, such
        # as Layout Builder iFrame Modals
        # --no-sandbox is needed to run. If absent, the message will be
        # 'The test wasn't able to connect to your webdriver instance.'
        # goog:chromeOptions is new as of Drupal 10.3
        # w3c:false is needed per #3240792
        MINK_DRIVER_ARGS_WEBDRIVER: '["chrome", {"browserName":"chrome","goog:chromeOptions":{"w3c":false, "args":["--disable-gpu","--headless", "--no-sandbox", "--disable-dev-shm-usage"]}}, "http://chrome:9515"]'
tooling:
  composer:
    service: appserver
    description: Run composer commands
    cmd:
      - php -d memory_limit=-1 /usr/local/bin/composer
  test:
    service: appserver
    description: Run all PHPUnit tests
    cmd:
      - sh .lando/test.sh
  drush:
    service: appserver
    cmd: drush --root=/app --uri=https://drupal-core-development-project.lndo.site

Model .lando/phpunit.xml file

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  bootstrap="/app/web/core/tests/bootstrap.php"
  colors="true"
  beStrictAboutTestsThatDoNotTestAnything="true"
  beStrictAboutOutputDuringTests="true"
  beStrictAboutChangesToGlobalState="true"
  cacheResult="false"
  xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
  cacheDirectory=".phpunit.cache">
  <php>
    <ini name="error_reporting" value="32767" />
    <ini name="memory_limit" value="-1" />
    <env name="SIMPLETEST_BASE_URL" value="http://drupal-core-development-project.lndo.site"
      force="true" />
  </php>
  <extensions>
    <bootstrap class="Drupal\TestTools\Extension\HtmlLogging\HtmlOutputLogger">
      <parameter name="outputDirectory" value="/app/web/sites/simpletest/browser_output" />
      <parameter name="verbose" value="true" />
    </bootstrap>
  </extensions>
  <testsuites>
    <testsuite name="unit">
      <file>./tests/TestSuites/UnitTestSuite.php</file>
    </testsuite>
    <testsuite name="kernel">
      <file>./tests/TestSuites/KernelTestSuite.php</file>
    </testsuite>
    <testsuite name="functional">
      <file>./tests/TestSuites/FunctionalTestSuite.php</file>
    </testsuite>
    <testsuite name="functional-javascript">
      <file>./tests/TestSuites/FunctionalJavascriptTestSuite.php</file>
    </testsuite>
    <testsuite name="build">
      <file>./tests/TestSuites/BuildTestSuite.php</file>
    </testsuite>
  </testsuites>
  <source>
    <include>
      <directory>./includes</directory>
      <directory>./lib</directory>
      <directory>./modules</directory>
      <directory>../modules</directory>
      <directory>../sites</directory>
    </include>
    <exclude>
      <directory>./modules/*/src/Tests</directory>
      <directory>./modules/*/tests</directory>
      <directory>../modules/*/src/Tests</directory>
      <directory>../modules/*/tests</directory>
      <directory>../modules/*/*/src/Tests</directory>
      <directory>../modules/*/*/tests</directory>
      <directory suffix=".api.php">./lib/**</directory>
      <directory suffix=".api.php">./modules/**</directory>
      <directory suffix=".api.php">../modules/**</directory>
    </exclude>
  </source>
</phpunit>

Model .lando/test.sh file

# We need to add drupal/core-dev for PHPUnit
# We do this in a check here so as not to run `composer require`
# every time we want to run tests.
if ! grep -q "drupal/core-dev" composer.json; then
  echo "Adding core tooling. This may take a moment...";
  composer require "drupal/core-dev-pinned"
fi
mkdir -p /app/web/sites/simpletest/browser_output
chmod 777 /app/web/sites/simpletest/browser_output
# Now we actually run the command...
/app/vendor/bin/phpunit -c /app/.lando/phpunit.xml --stop-on-failure --display-deprecations --testdox $1

Executing PHPUnit tests

## lando test <path/to/test>
lando test web/core/modules/text/tests/src/FunctionalJavascript/TextareaWithSummaryTest.php

Help improve this page

Page status: No known problems

You can: