This addon includes commonly used DDEV commands for Drupal development with focus on code quality and linting.
-
PHP Tools
phpcs- PHP CodeSniffer with Drupal standardsphpstan- PHP Static Analysis Tooltwigcs- Twig CodeSniffer
-
JavaScript & CSS
eslint- JavaScript/ECMAScript linterstylelint- CSS/SCSS linter
-
General
cspell- Spell Checker for Code
dev-lint- Run all linters on changed filesdev-lint-all- Run all linters on all files
install-drupal- Install Drupal using existing configurations and a thin database. Runsddev post-installautomatically after installation if the commands's file exists.
ddev add-on get Vardot/ddev-dev-tools
ddev restartEach linting tool can be run in three modes:
1. Check Git Changes (Default)
ddev dev-phpcs # Check PHP files in git diff
ddev dev-eslint # Check JS files in git diff
ddev dev-stylelint # Check CSS files in git diff
ddev dev-twigcs # Check Twig files in git diff
ddev dev-cspell # Check text files in git diff2. Check Specific Files
ddev dev-phpcs --files=path/to/file1.php,path/to/file2.module
ddev dev-eslint --files=path/to/file1.js,path/to/file2.js
ddev dev-stylelint --files=path/to/file1.css,path/to/file2.css
ddev dev-twigcs --files=path/to/file1.twig,path/to/file2.twig
ddev dev-cspell --files=path/to/file1.txt,path/to/file2.md3. Check All Files
ddev dev-phpcs --all # Check all PHP files
ddev dev-eslint --all # Check all JS files
ddev dev-stylelint --all # Check all CSS files
ddev dev-twigcs --all # Check all Twig files
ddev dev-cspell --all # Check all text filesCheck Changed Files
ddev dev-lint # Run all linters on git changesCheck All Files
ddev dev-lint-all # Run all linters on all filesPHPCS Extensions
# Check specific file extensions
ddev dev-phpcs --ext=php,module,incThis addon supports various CI/CD platforms including BitBucket Pipelines, GitHub Actions, Azure DevOps, and GitLab CI.
Set these variables in your CI environment:
IS_CI=TRUE
PHP_CHANGED_FILES="file1.php,file2.module"
JS_CHANGED_FILES="file1.js,file2.js"
STYLE_CHANGED_FILES="file1.css,file2.css"
TWIG_CHANGED_FILES="file1.twig,file2.twig"
TEXT_CHANGED_FILES="file1.md,file2.txt"
CYPRESS_TEST_CONTENT_AVAILABLE="true" # Set automatically by install-drupal command based on filesystem detection- Create a pipeline configuration file:
cp config.pipeline.yaml.example .ddev/config.pipeline.yaml- Or generate it dynamically in your pipeline:
BitBucket Pipelines
steps:
- step:
script:
- |
cat > .ddev/config.pipeline.yaml << EOF
web_environment:
- IS_CI=TRUE
- PHP_CHANGED_FILES=${PHP_CHANGED_FILES}
- JS_CHANGED_FILES=${JS_CHANGED_FILES}
- STYLE_CHANGED_FILES=${STYLE_CHANGED_FILES}
- TWIG_CHANGED_FILES=${TWIG_CHANGED_FILES}
- TEXT_CHANGED_FILES=${TEXT_CHANGED_FILES}
EOFGitHub Actions
jobs:
lint:
steps:
- run: |
cat > .ddev/config.pipeline.yaml << EOF
web_environment:
- IS_CI=TRUE
- PHP_CHANGED_FILES=${{ env.PHP_CHANGED_FILES }}
- JS_CHANGED_FILES=${{ env.JS_CHANGED_FILES }}
- STYLE_CHANGED_FILES=${{ env.STYLE_CHANGED_FILES }}
- TWIG_CHANGED_FILES=${{ env.TWIG_CHANGED_FILES }}
- TEXT_CHANGED_FILES=${{ env.TEXT_CHANGED_FILES }}
EOFAzure DevOps
steps:
- bash: |
cat > .ddev/config.pipeline.yaml << EOF
web_environment:
- IS_CI=TRUE
- PHP_CHANGED_FILES=$(PHP_CHANGED_FILES)
- JS_CHANGED_FILES=$(JS_CHANGED_FILES)
- STYLE_CHANGED_FILES=$(STYLE_CHANGED_FILES)
- TWIG_CHANGED_FILES=$(TWIG_CHANGED_FILES)
- TEXT_CHANGED_FILES=$(TEXT_CHANGED_FILES)
EOF- Then run the linting command:
ddev dev-lintAfter running ddev install-drupal, the module detection result is saved to .cypress_test_content_status file. Source this file in your pipeline scripts:
# Run Drupal installation which detects the module
ddev install-drupal
# Source the module detection result
if [ -f .cypress_test_content_status ]; then
source .cypress_test_content_status
fi
# Use the environment variable
if [ "${CYPRESS_TEST_CONTENT_AVAILABLE}" = "true" ]; then
echo "Running Cypress tests with test content"
ddev cypress-headless
else
echo "Skipping Cypress tests - no test content module"
fi-
Playwright
playwright-install- Install Playwright project dependencies fromtests/playwright-test- Run Playwright tests inside the Playwright containerdev-playwright- Wrapper that runs all Playwright tests with optional filtering
-
Cypress
cypress-open- Open interactive Cypress windowcypress-run- Run Cypress tests in headless modecypress-install- Install additional npm packages for Cucumber support
-
PHPUnit
dev-phpunit- Run PHPUnit tests on custom modules
This addon includes a dedicated Playwright container and command set for running browser tests in a DDEV-friendly way.
- A
playwrightservice based on the official Microsoft Playwright image - A
ddev playwright-installcommand that installs project dependencies fromtests/ - A
ddev playwright-testcommand that runs Playwright directly inside the container - A
ddev dev-playwrightcommand that adds CI/local behavior on top of the raw test runner
Playwright is expected to live under tests/playwright/ in your project. The smart runner looks for test files such as:
*.spec.**.test.**.cy.*
If those files exist, ddev dev-playwright runs Playwright. If not, your pipeline can fall back to Cypress or skip automated tests entirely.
# Install dependencies for the Playwright project
ddev playwright-install
# Run all Playwright tests
ddev playwright-test
# Run through the smart wrapper
ddev dev-playwrightddev dev-playwright
ddev dev-playwright --production
ddev dev-playwright --grep=@smoke
ddev dev-playwright --workers=4
ddev dev-playwright --max-failures=3
ddev dev-playwright --has-tests| Flag | Default | Description |
|---|---|---|
--production |
β | Run the full suite excluding @slow tests. Auto-detected from BITBUCKET_PR_DESTINATION_BRANCH in CI. |
--grep=<pattern> |
β | Run only tests matching a tag or name pattern. |
--workers=<n> |
β | Number of parallel Playwright workers. |
--max-failures=<n> |
1 |
Stop the run after N test failures. |
--has-tests |
β | Pre-check mode: exits 0 if tests would run, exits 1 if not. Useful before expensive steps like ddev install-drupal. |
--all |
β | Alias for the default behaviour (run all tests). Kept for backwards compatibility. |
Running ddev dev-playwright with no flags runs the full Playwright suite β equivalent to ddev playwright-test. Pass --production or --grep to narrow the run.
The Playwright container exposes the primary DDEV URL as PLAYWRIGHT_BASE_URL.
If your test app needs credentials, the container also provides Drupal login defaults through environment variables.
Place your Playwright config under tests/ so the addon can discover it automatically.
It's recommended to run ddev cypress-open first to create configuration and support files. This addon sets CYPRESS_baseUrl to DDEV's primary URL in the docker-compose.cypress.yaml.
Note: This addon uses the latest official Cypress Docker image to ensure up-to-date testing capabilities and compatibility.
For Behavior-Driven Development (BDD) with Gherkin syntax:
# Install Cucumber preprocessor packages
ddev cypress-install
# Copy example configuration
cp examples/cypress.config.js.example-[cucumber] cypress.config.jsThis enables writing tests in natural language:
Feature: User Login
Scenario: Successful login
Given I visit the login page
When I enter valid credentials
Then I should be logged inThe addon includes example configurations:
cypress.config.js.example-[cucumber]- Configuration with Cucumber/Gherkin supportphpunit.xml.example- PHPUnit configuration for Drupal testing
To use Cypress, you'll need to configure your display settings based on your OS:
macOS:
brew install xquartz --cask
open -a XQuartz
# Check "Allow connections from network clients" in XQuartz preferences
# Restart your Mac
xhost + 127.0.0.1
# Add to .ddev/docker-compose.cypress_extra.yaml:
services:
cypress:
environment:
- DISPLAY=host.docker.internal:0Linux:
export DISPLAY=:0
xhost +Windows: Install GWSL or VcXsrv
Run PHPUnit tests on your custom Drupal modules.
PHPUnit requires drupal/core-dev to be installed:
ddev composer require --dev drupal/core-dev --with-all-dependencies- Copy the example configuration to your project root:
cp examples/phpunit.xml.example phpunit.xml- Customize the configuration as needed:
- Update
SIMPLETEST_BASE_URLif using a different local URL - Modify database connection in
SIMPLETEST_DB - Adjust
BROWSERTEST_OUTPUT_DIRECTORYfor test output location - Configure coverage paths to include/exclude specific directories
- Update
ddev dev-phpunitThis command will:
- Check if
drupal/core-devis installed - Locate your PHPUnit configuration file (
phpunit.xml,phpunit.xml.dist, or core's default) - Run tests on custom modules in
docroot/modules/custom/orweb/modules/custom/ - Display results with colors and test documentation format
The command searches for configuration files in this order:
/var/www/html/phpunit.xml/var/www/html/phpunit.xml.dist/var/www/html/docroot/core/phpunit.xml.dist/var/www/html/web/core/phpunit.xml.dist