Running PHPUnit tests in Lando
There are a couple options for configuring PHPUnit and running PHPUnit tests in Lando.
Preconfigured tooling for Lando+Drupal+PHPUnit
- Lando + Drupal Contributions (good for Drupal 9/10) automates the steps for configuration, as well as adds commands to run tests, reinstall the site with fresh database, pull down and apply a patch, revert a patch, and create a patch from the current branch. See its repository for more details.
- Joachim's Drupal Core Development Composer Project includes an example of integrated Lando tooling for running PHPUnit tests. See the pull request.
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.shCreate 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 $ARGSModify 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.siteModel .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 $1Executing PHPUnit tests
## lando test <path/to/test>
lando test web/core/modules/text/tests/src/FunctionalJavascript/TextareaWithSummaryTest.phpHelp improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion
Still on Drupal 7? Security support for Drupal 7 ended on 5 January 2025. Please visit our Drupal 7 End of Life resources page to review all of your options.