diff --git a/.env.example b/.env.example index 1ca8f9658dbef..a90402036839c 100644 --- a/.env.example +++ b/.env.example @@ -45,6 +45,16 @@ LOCAL_PHP_XDEBUG_MODE=develop,debug # Whether or not to enable Memcached. LOCAL_PHP_MEMCACHED=false +## +# Whether or not to enable PCOV. +# +# PCOV is not interoperable with Xdebug. To use PCOV, `LOCAL_PHP_XDEBUG` must be +# set to `false`. When both are enabled, Xdebug is used and PCOV is disabled. +# +# PCOV is only available for PHP 7.4 and higher. +## +LOCAL_PHP_PCOV=false + ## # The database software to use. # diff --git a/.github/workflows/reusable-phpunit-tests-v3.yml b/.github/workflows/reusable-phpunit-tests-v3.yml index 1e1c85ad0a453..01dd82e983940 100644 --- a/.github/workflows/reusable-phpunit-tests-v3.yml +++ b/.github/workflows/reusable-phpunit-tests-v3.yml @@ -114,6 +114,7 @@ env: LOCAL_PHP: ${{ inputs.php }}-fpm LOCAL_PHP_XDEBUG: false LOCAL_PHP_XDEBUG_MODE: 'develop,debug' + LOCAL_PHP_PCOV: ${{ inputs.coverage-report }} LOCAL_DB_TYPE: ${{ inputs.db-type }} LOCAL_DB_VERSION: ${{ inputs.db-version }} LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }} @@ -292,31 +293,6 @@ jobs: - name: Install WordPress run: npm run env:install - # Installs PCOV as the code coverage driver for the PHPUnit run below. - # - # The INI directives tune PCOV for WordPress's codebase: - # - `pcov.enabled` keeps the Zend hooks active (this is the default, but - # stated explicitly for clarity). - # - `pcov.directory` restricts instrumentation to `src/`, so PCOV does not - # record hits for `vendor/`, `tests/`, or WordPress test fixtures that - # PHPUnit would discard at report time anyway. - # - `pcov.initial.files` pre-sizes the internal file tracking array for - # the thousands of files under `src/`, avoiding reallocation churn - # during test warmup. The default of 64 is far too low here. - - name: Install PCOV coverage driver - if: ${{ inputs.coverage-report }} - run: | - docker compose exec -T -u 0 php sh -c ' - pecl install --force pcov-1.0.12 && - docker-php-ext-enable pcov && - { - echo "pcov.enabled=1" - echo "pcov.directory=/var/www/src" - echo "pcov.initial.files=10000" - } >> /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini && - php -m | grep -i pcov - ' - - name: Run external HTTP tests if: ${{ ! inputs.multisite && ! inputs.phpunit-test-groups && ! inputs.coverage-report }} continue-on-error: ${{ inputs.allow-errors }} diff --git a/README.md b/README.md index 637e24359f034..0f41da84643bd 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,9 @@ npm run test:coverage The command will generate three coverage reports in HTML, PHP, and text formats, saving them in the `coverage` folder. -**Note:** xDebug is required to generate a code coverage report, which can slow down PHPUnit significantly. Passing selection-based options such as `--group` or `--filter` can decrease the overall time required but will result in an incomplete report. +**Note:** A code coverage driver is required to generate a code coverage report. By default, xDebug is used, which can slow down PHPUnit significantly. PCOV is a faster alternative that is available for PHP 7.4 and higher. To use it, set `LOCAL_PHP_PCOV` to `true` and `LOCAL_PHP_XDEBUG` to `false` in your `.env` file. + +Passing selection-based options such as `--group` or `--filter` can decrease the overall time required but will result in an incomplete report. #### To restart the development environment diff --git a/docker-compose.yml b/docker-compose.yml index 61a123f7427c7..62bce43174293 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,7 @@ services: environment: LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} XDEBUG_MODE: ${LOCAL_PHP_XDEBUG_MODE-develop,debug} + LOCAL_PHP_PCOV: ${LOCAL_PHP_PCOV-false} LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} PHP_FPM_UID: ${PHP_FPM_UID-1000} PHP_FPM_GID: ${PHP_FPM_GID-1000} @@ -118,6 +119,7 @@ services: environment: LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} + LOCAL_PHP_PCOV: ${LOCAL_PHP_PCOV-false} LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} PHP_FPM_UID: ${PHP_FPM_UID-1000} PHP_FPM_GID: ${PHP_FPM_GID-1000} diff --git a/tools/local-env/php-config.ini b/tools/local-env/php-config.ini index 6f98802e5c68a..c01d94af40aa2 100644 --- a/tools/local-env/php-config.ini +++ b/tools/local-env/php-config.ini @@ -5,3 +5,8 @@ post_max_size = 1G xdebug.start_with_request=trigger xdebug.discover_client_host=true xdebug.client_host=host.docker.internal + +; Pre-sizes PCOV's internal file tables (default: 64) to more than the number +; of PHP files loaded during a test run, including test and vendor files. +; This avoids repeatedly resizing the tables as files are loaded. +pcov.initial.files=10000 diff --git a/tools/local-env/scripts/docker.js b/tools/local-env/scripts/docker.js index a6b0f4e0af38e..0ef6d469d19d6 100644 --- a/tools/local-env/scripts/docker.js +++ b/tools/local-env/scripts/docker.js @@ -8,7 +8,11 @@ local_env_utils.ensure_env_file(); dotenvExpand.expand( dotenv.config() ); -if ( process.argv.includes( '--coverage-html' ) ) { +// Use Xdebug to generate HTML code coverage reports, unless PCOV is enabled and Xdebug is not. +if ( + process.argv.includes( '--coverage-html' ) && + ( process.env.LOCAL_PHP_PCOV !== 'true' || process.env.LOCAL_PHP_XDEBUG === 'true' ) +) { process.env.LOCAL_PHP_XDEBUG = 'true'; process.env.LOCAL_PHP_XDEBUG_MODE = 'coverage'; }